Merge "Add Rx RemoteMediator samples" into androidx-master-dev
diff --git a/activity/activity/api/api_lint.ignore b/activity/activity/api/api_lint.ignore
index d22641b..2784aac 100644
--- a/activity/activity/api/api_lint.ignore
+++ b/activity/activity/api/api_lint.ignore
@@ -3,10 +3,6 @@
     ComponentActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead.
 
 
-KotlinOperator: androidx.activity.result.ActivityResultRegistry#invoke(int, androidx.activity.result.contract.ActivityResultContract<I,O>, I, androidx.core.app.ActivityOptionsCompat):
-    Method can be invoked with function call syntax from Kotlin: `invoke` (this is usually desirable; just make sure it makes sense for this type of object)
-
-
 MissingNullability: androidx.activity.ComponentActivity#startActivityForResult(android.content.Intent, int) parameter #0:
     Missing nullability on parameter `intent` in method `startActivityForResult`
 MissingNullability: androidx.activity.ComponentActivity#startActivityForResult(android.content.Intent, int, android.os.Bundle) parameter #0:
diff --git a/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml b/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml
index b89cf16..5f8aea8 100644
--- a/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml
+++ b/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml
@@ -24,5 +24,8 @@
         android:name=".AdsIdentifierBenchmarkApplication"
         android:debuggable="false"
         tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
diff --git a/annotation/annotation-experimental/api/1.1.0-alpha01.txt b/annotation/annotation-experimental/api/1.1.0-alpha01.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/1.1.0-alpha01.txt
+++ b/annotation/annotation-experimental/api/1.1.0-alpha01.txt
@@ -6,6 +6,8 @@
   }
 
   public enum Experimental.Level {
+    method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.annotation.experimental.Experimental.Level[] values();
     enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
     enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
   }
diff --git a/annotation/annotation-experimental/api/current.txt b/annotation/annotation-experimental/api/current.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/current.txt
+++ b/annotation/annotation-experimental/api/current.txt
@@ -6,6 +6,8 @@
   }
 
   public enum Experimental.Level {
+    method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.annotation.experimental.Experimental.Level[] values();
     enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
     enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
   }
diff --git a/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt b/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt
+++ b/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt
@@ -6,6 +6,8 @@
   }
 
   public enum Experimental.Level {
+    method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.annotation.experimental.Experimental.Level[] values();
     enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
     enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
   }
diff --git a/annotation/annotation-experimental/api/public_plus_experimental_current.txt b/annotation/annotation-experimental/api/public_plus_experimental_current.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/public_plus_experimental_current.txt
+++ b/annotation/annotation-experimental/api/public_plus_experimental_current.txt
@@ -6,6 +6,8 @@
   }
 
   public enum Experimental.Level {
+    method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.annotation.experimental.Experimental.Level[] values();
     enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
     enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
   }
diff --git a/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt b/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt
+++ b/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt
@@ -6,6 +6,8 @@
   }
 
   public enum Experimental.Level {
+    method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.annotation.experimental.Experimental.Level[] values();
     enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
     enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
   }
diff --git a/annotation/annotation-experimental/api/restricted_current.txt b/annotation/annotation-experimental/api/restricted_current.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/restricted_current.txt
+++ b/annotation/annotation-experimental/api/restricted_current.txt
@@ -6,6 +6,8 @@
   }
 
   public enum Experimental.Level {
+    method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.annotation.experimental.Experimental.Level[] values();
     enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
     enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
   }
diff --git a/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml b/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml
index 1302397..1c5fab4 100644
--- a/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml
+++ b/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml
@@ -23,6 +23,9 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
         <activity android:name="androidx.appcompat.app.AppCompatActivity"
             android:theme="@style/Theme.AppCompat"/>
     </application>
diff --git a/appcompat/appcompat/api/1.3.0-alpha01.txt b/appcompat/appcompat/api/1.3.0-alpha01.txt
index dc3c5ab..89aae44 100644
--- a/appcompat/appcompat/api/1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/1.3.0-alpha01.txt
@@ -449,11 +449,11 @@
     ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(int, int);
-    field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
-    field @android.view.ViewDebug.ExportedProperty public boolean expandable;
-    field @android.view.ViewDebug.ExportedProperty public int extraPixels;
-    field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
-    field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+    field public int cellsUsed;
+    field public boolean expandable;
+    field public int extraPixels;
+    field public boolean isOverflowButton;
+    field public boolean preventEdgeOffset;
   }
 
   public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/api_lint.ignore b/appcompat/appcompat/api/api_lint.ignore
index fd01b04a8..edddedd 100644
--- a/appcompat/appcompat/api/api_lint.ignore
+++ b/appcompat/appcompat/api/api_lint.ignore
@@ -613,8 +613,6 @@
     Missing nullability on method `onCreateInputConnection` return
 MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo) parameter #0:
     Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
-MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
     Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
 MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#setTextAppearance(android.content.Context, int) parameter #0:
@@ -625,14 +623,10 @@
     Missing nullability on parameter `info` in method `onInitializeAccessibilityNodeInfo`
 MissingNullability: androidx.appcompat.widget.AppCompatButton#onTextChanged(CharSequence, int, int, int) parameter #0:
     Missing nullability on parameter `text` in method `onTextChanged`
-MissingNullability: androidx.appcompat.widget.AppCompatButton#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatButton#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
     Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
 MissingNullability: androidx.appcompat.widget.AppCompatButton#setTextAppearance(android.content.Context, int) parameter #0:
     Missing nullability on parameter `context` in method `setTextAppearance`
-MissingNullability: androidx.appcompat.widget.AppCompatCheckBox#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatCheckBox#setButtonDrawable(android.graphics.drawable.Drawable) parameter #0:
     Missing nullability on parameter `buttonDrawable` in method `setButtonDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatCheckedTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo):
@@ -647,26 +641,18 @@
     Missing nullability on method `onCreateInputConnection` return
 MissingNullability: androidx.appcompat.widget.AppCompatEditText#onCreateInputConnection(android.view.inputmethod.EditorInfo) parameter #0:
     Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
-MissingNullability: androidx.appcompat.widget.AppCompatEditText#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatEditText#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
     Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
 MissingNullability: androidx.appcompat.widget.AppCompatEditText#setTextAppearance(android.content.Context, int) parameter #0:
     Missing nullability on parameter `context` in method `setTextAppearance`
-MissingNullability: androidx.appcompat.widget.AppCompatImageButton#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatImageButton#setImageBitmap(android.graphics.Bitmap) parameter #0:
     Missing nullability on parameter `bm` in method `setImageBitmap`
-MissingNullability: androidx.appcompat.widget.AppCompatImageView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatImageView#setImageBitmap(android.graphics.Bitmap) parameter #0:
     Missing nullability on parameter `bm` in method `setImageBitmap`
 MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo):
     Missing nullability on method `onCreateInputConnection` return
 MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo) parameter #0:
     Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
-MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#setTextAppearance(android.content.Context, int) parameter #0:
     Missing nullability on parameter `context` in method `setTextAppearance`
 MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#AppCompatRadioButton(android.content.Context) parameter #0:
@@ -675,8 +661,6 @@
     Missing nullability on parameter `context` in method `AppCompatRadioButton`
 MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#AppCompatRadioButton(android.content.Context, android.util.AttributeSet, int) parameter #0:
     Missing nullability on parameter `context` in method `AppCompatRadioButton`
-MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#setButtonDrawable(android.graphics.drawable.Drawable) parameter #0:
     Missing nullability on parameter `buttonDrawable` in method `setButtonDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatSeekBar#onDraw(android.graphics.Canvas) parameter #0:
@@ -697,8 +681,6 @@
     Missing nullability on parameter `event` in method `onTouchEvent`
 MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setAdapter(android.widget.SpinnerAdapter) parameter #0:
     Missing nullability on parameter `adapter` in method `setAdapter`
-MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setPopupBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
     Missing nullability on parameter `background` in method `setPopupBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setPrompt(CharSequence) parameter #0:
@@ -711,8 +693,6 @@
     Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
 MissingNullability: androidx.appcompat.widget.AppCompatTextView#onTextChanged(CharSequence, int, int, int) parameter #0:
     Missing nullability on parameter `text` in method `onTextChanged`
-MissingNullability: androidx.appcompat.widget.AppCompatTextView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
-    Missing nullability on parameter `background` in method `setBackgroundDrawable`
 MissingNullability: androidx.appcompat.widget.AppCompatTextView#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
     Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
 MissingNullability: androidx.appcompat.widget.AppCompatTextView#setTextAppearance(android.content.Context, int) parameter #0:
diff --git a/appcompat/appcompat/api/current.txt b/appcompat/appcompat/api/current.txt
index dc3c5ab..89aae44 100644
--- a/appcompat/appcompat/api/current.txt
+++ b/appcompat/appcompat/api/current.txt
@@ -449,11 +449,11 @@
     ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(int, int);
-    field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
-    field @android.view.ViewDebug.ExportedProperty public boolean expandable;
-    field @android.view.ViewDebug.ExportedProperty public int extraPixels;
-    field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
-    field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+    field public int cellsUsed;
+    field public boolean expandable;
+    field public int extraPixels;
+    field public boolean isOverflowButton;
+    field public boolean preventEdgeOffset;
   }
 
   public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt b/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
index 09e7731..dca14b8 100644
--- a/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
@@ -449,11 +449,11 @@
     ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(int, int);
-    field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
-    field @android.view.ViewDebug.ExportedProperty public boolean expandable;
-    field @android.view.ViewDebug.ExportedProperty public int extraPixels;
-    field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
-    field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+    field public int cellsUsed;
+    field public boolean expandable;
+    field public int extraPixels;
+    field public boolean isOverflowButton;
+    field public boolean preventEdgeOffset;
   }
 
   public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/public_plus_experimental_current.txt b/appcompat/appcompat/api/public_plus_experimental_current.txt
index 09e7731..dca14b8 100644
--- a/appcompat/appcompat/api/public_plus_experimental_current.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_current.txt
@@ -449,11 +449,11 @@
     ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(int, int);
-    field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
-    field @android.view.ViewDebug.ExportedProperty public boolean expandable;
-    field @android.view.ViewDebug.ExportedProperty public int extraPixels;
-    field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
-    field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+    field public int cellsUsed;
+    field public boolean expandable;
+    field public int extraPixels;
+    field public boolean isOverflowButton;
+    field public boolean preventEdgeOffset;
   }
 
   public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt b/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
index 6f63cec..a210c6c6 100644
--- a/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
@@ -936,14 +936,14 @@
     method public int getGroupId();
     method public android.graphics.drawable.Drawable! getIcon();
     method public android.content.Intent! getIntent();
-    method @android.view.ViewDebug.CapturedViewProperty public int getItemId();
+    method public int getItemId();
     method public android.view.ContextMenu.ContextMenuInfo! getMenuInfo();
     method public char getNumericShortcut();
     method public int getOrder();
     method public int getOrdering();
     method public android.view.SubMenu! getSubMenu();
     method public androidx.core.view.ActionProvider! getSupportActionProvider();
-    method @android.view.ViewDebug.CapturedViewProperty public CharSequence! getTitle();
+    method public CharSequence! getTitle();
     method public CharSequence! getTitleCondensed();
     method public boolean hasCollapsibleActionView();
     method public boolean hasSubMenu();
@@ -1295,11 +1295,11 @@
     ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(int, int);
-    field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
-    field @android.view.ViewDebug.ExportedProperty public boolean expandable;
-    field @android.view.ViewDebug.ExportedProperty public int extraPixels;
-    field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
-    field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+    field public int cellsUsed;
+    field public boolean expandable;
+    field public int extraPixels;
+    field public boolean isOverflowButton;
+    field public boolean preventEdgeOffset;
   }
 
   public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/restricted_current.txt b/appcompat/appcompat/api/restricted_current.txt
index 6f63cec..a210c6c6 100644
--- a/appcompat/appcompat/api/restricted_current.txt
+++ b/appcompat/appcompat/api/restricted_current.txt
@@ -936,14 +936,14 @@
     method public int getGroupId();
     method public android.graphics.drawable.Drawable! getIcon();
     method public android.content.Intent! getIntent();
-    method @android.view.ViewDebug.CapturedViewProperty public int getItemId();
+    method public int getItemId();
     method public android.view.ContextMenu.ContextMenuInfo! getMenuInfo();
     method public char getNumericShortcut();
     method public int getOrder();
     method public int getOrdering();
     method public android.view.SubMenu! getSubMenu();
     method public androidx.core.view.ActionProvider! getSupportActionProvider();
-    method @android.view.ViewDebug.CapturedViewProperty public CharSequence! getTitle();
+    method public CharSequence! getTitle();
     method public CharSequence! getTitleCondensed();
     method public boolean hasCollapsibleActionView();
     method public boolean hasSubMenu();
@@ -1295,11 +1295,11 @@
     ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
     ctor public ActionMenuView.LayoutParams(int, int);
-    field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
-    field @android.view.ViewDebug.ExportedProperty public boolean expandable;
-    field @android.view.ViewDebug.ExportedProperty public int extraPixels;
-    field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
-    field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+    field public int cellsUsed;
+    field public boolean expandable;
+    field public int extraPixels;
+    field public boolean isOverflowButton;
+    field public boolean preventEdgeOffset;
   }
 
   public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appsearch/appsearch/api/1.0.0-alpha01.txt b/appsearch/appsearch/api/1.0.0-alpha01.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/1.0.0-alpha01.txt
@@ -1,6 +1,27 @@
 // Signature format: 3.0
 package androidx.appsearch.app {
 
+  public final class AppSearchBatchResult<KeyType, ValueType> {
+    method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+    method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+    method public boolean isSuccess();
+  }
+
+  public final class AppSearchResult<ValueType> {
+    method public String? getErrorMessage();
+    method public int getResultCode();
+    method public ValueType? getResultValue();
+    method public boolean isSuccess();
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+    field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+    field public static final int RESULT_IO_ERROR = 4; // 0x4
+    field public static final int RESULT_NOT_FOUND = 6; // 0x6
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+    field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+  }
+
   public final class AppSearchSchema {
   }
 
diff --git a/appsearch/appsearch/api/current.txt b/appsearch/appsearch/api/current.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/current.txt
+++ b/appsearch/appsearch/api/current.txt
@@ -1,6 +1,27 @@
 // Signature format: 3.0
 package androidx.appsearch.app {
 
+  public final class AppSearchBatchResult<KeyType, ValueType> {
+    method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+    method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+    method public boolean isSuccess();
+  }
+
+  public final class AppSearchResult<ValueType> {
+    method public String? getErrorMessage();
+    method public int getResultCode();
+    method public ValueType? getResultValue();
+    method public boolean isSuccess();
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+    field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+    field public static final int RESULT_IO_ERROR = 4; // 0x4
+    field public static final int RESULT_NOT_FOUND = 6; // 0x6
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+    field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+  }
+
   public final class AppSearchSchema {
   }
 
diff --git a/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt b/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -1,6 +1,27 @@
 // Signature format: 3.0
 package androidx.appsearch.app {
 
+  public final class AppSearchBatchResult<KeyType, ValueType> {
+    method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+    method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+    method public boolean isSuccess();
+  }
+
+  public final class AppSearchResult<ValueType> {
+    method public String? getErrorMessage();
+    method public int getResultCode();
+    method public ValueType? getResultValue();
+    method public boolean isSuccess();
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+    field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+    field public static final int RESULT_IO_ERROR = 4; // 0x4
+    field public static final int RESULT_NOT_FOUND = 6; // 0x6
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+    field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+  }
+
   public final class AppSearchSchema {
   }
 
diff --git a/appsearch/appsearch/api/public_plus_experimental_current.txt b/appsearch/appsearch/api/public_plus_experimental_current.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/public_plus_experimental_current.txt
+++ b/appsearch/appsearch/api/public_plus_experimental_current.txt
@@ -1,6 +1,27 @@
 // Signature format: 3.0
 package androidx.appsearch.app {
 
+  public final class AppSearchBatchResult<KeyType, ValueType> {
+    method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+    method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+    method public boolean isSuccess();
+  }
+
+  public final class AppSearchResult<ValueType> {
+    method public String? getErrorMessage();
+    method public int getResultCode();
+    method public ValueType? getResultValue();
+    method public boolean isSuccess();
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+    field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+    field public static final int RESULT_IO_ERROR = 4; // 0x4
+    field public static final int RESULT_NOT_FOUND = 6; // 0x6
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+    field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+  }
+
   public final class AppSearchSchema {
   }
 
diff --git a/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt b/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
@@ -1,6 +1,27 @@
 // Signature format: 3.0
 package androidx.appsearch.app {
 
+  public final class AppSearchBatchResult<KeyType, ValueType> {
+    method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+    method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+    method public boolean isSuccess();
+  }
+
+  public final class AppSearchResult<ValueType> {
+    method public String? getErrorMessage();
+    method public int getResultCode();
+    method public ValueType? getResultValue();
+    method public boolean isSuccess();
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+    field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+    field public static final int RESULT_IO_ERROR = 4; // 0x4
+    field public static final int RESULT_NOT_FOUND = 6; // 0x6
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+    field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+  }
+
   public final class AppSearchSchema {
   }
 
diff --git a/appsearch/appsearch/api/restricted_current.txt b/appsearch/appsearch/api/restricted_current.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/restricted_current.txt
+++ b/appsearch/appsearch/api/restricted_current.txt
@@ -1,6 +1,27 @@
 // Signature format: 3.0
 package androidx.appsearch.app {
 
+  public final class AppSearchBatchResult<KeyType, ValueType> {
+    method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+    method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+    method public boolean isSuccess();
+  }
+
+  public final class AppSearchResult<ValueType> {
+    method public String? getErrorMessage();
+    method public int getResultCode();
+    method public ValueType? getResultValue();
+    method public boolean isSuccess();
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+    field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+    field public static final int RESULT_IO_ERROR = 4; // 0x4
+    field public static final int RESULT_NOT_FOUND = 6; // 0x6
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+    field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+  }
+
   public final class AppSearchSchema {
   }
 
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java
index 16b51a7..1c52c2f 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java
@@ -18,7 +18,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
 import androidx.collection.ArrayMap;
 import androidx.core.util.Preconditions;
 
@@ -30,9 +29,7 @@
  *
  * @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}.
  * @param <ValueType> The type of result objects associated with the keys.
- * @hide
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public final class AppSearchBatchResult<KeyType, ValueType> {
     @NonNull private final Map<KeyType, ValueType> mSuccesses;
     @NonNull private final Map<KeyType, AppSearchResult<ValueType>> mFailures;
@@ -75,7 +72,6 @@
      * Asserts that this {@link AppSearchBatchResult} has no failures.
      * @hide
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public void checkSuccess() {
         if (!isSuccess()) {
             throw new IllegalStateException("AppSearchBatchResult has failures: " + this);
@@ -93,6 +89,7 @@
      *
      * @param <KeyType> The type of keys.
      * @param <ValueType> The type of result objects associated with the keys.
+     * @hide
      */
     public static final class Builder<KeyType, ValueType> {
         private final Map<KeyType, ValueType> mSuccesses = new ArrayMap<>();
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java
index 750542f..d2fd6be 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java
@@ -19,7 +19,6 @@
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
 import androidx.core.util.ObjectsCompat;
 
 import java.lang.annotation.Retention;
@@ -29,11 +28,12 @@
  * Information about the success or failure of an AppSearch call.
  *
  * @param <ValueType> The type of result object for successful calls.
- * @hide
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public final class AppSearchResult<ValueType> {
-    /** Result codes from {@link AppSearchManager} methods.  */
+    /**
+     * Result codes from {@link AppSearchManager} methods.
+     * @hide
+     */
     @IntDef(value = {
             RESULT_OK,
             RESULT_UNKNOWN_ERROR,
@@ -111,9 +111,10 @@
      *
      * <p>If {@link #isSuccess} is {@code false}, the result value is always {@code null}. The value
      * may be {@code null} even if {@link #isSuccess} is {@code true}. See the documentation of the
-     * particular {@link AppSearchManager} call producing this {@link AppSearchResult} for what is
+     * particular {@code AppSearchManager} call producing this {@link AppSearchResult} for what is
      * returned by {@link #getResultValue}.
      */
+    // TODO(b/157082794): Linkify AppSearchManager once that API is public
     @Nullable
     public ValueType getResultValue() {
         return mResultValue;
@@ -124,9 +125,10 @@
      *
      * <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}. The error
      * message may be {@code null} even if {@link #isSuccess} is {@code false}. See the
-     * documentation of the particular {@link AppSearchManager} call producing this
+     * documentation of the particular {@code AppSearchManager} call producing this
      * {@link AppSearchResult} for what is returned by {@link #getErrorMessage}.
      */
+    // TODO(b/157082794): Linkify AppSearchManager once that API is public
     @Nullable
     public String getErrorMessage() {
         return mErrorMessage;
@@ -136,7 +138,6 @@
      * Asserts that this {@link AppSearchResult} is successful.
      * @hide
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public void checkSuccess() {
         if (!isSuccess()) {
             throw new IllegalStateException("AppSearchResult is a failure: " + this);
@@ -171,14 +172,20 @@
         return "[FAILURE(" + mResultCode + ")]: " + mErrorMessage;
     }
 
-    /** Creates a new successful {@link AppSearchResult}. */
+    /**
+     * Creates a new successful {@link AppSearchResult}.
+     * @hide
+     */
     @NonNull
     public static <ValueType> AppSearchResult<ValueType> newSuccessfulResult(
             @Nullable ValueType value) {
         return new AppSearchResult<>(RESULT_OK, value, /*errorMessage=*/ null);
     }
 
-    /** Creates a new failed {@link AppSearchResult}.  */
+    /**
+     * Creates a new failed {@link AppSearchResult}.
+     * @hide
+     */
     @NonNull
     public static <ValueType> AppSearchResult<ValueType> newFailedResult(
             @ResultCode int resultCode, @Nullable String errorMessage) {
diff --git a/autofill/autofill/api/1.1.0-alpha02.txt b/autofill/autofill/api/1.1.0-alpha02.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/1.1.0-alpha02.txt
+++ b/autofill/autofill/api/1.1.0-alpha02.txt
@@ -156,6 +156,7 @@
   public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
     method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+    method public int getLayoutDirection();
     method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
     method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+    method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/current.txt b/autofill/autofill/api/current.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/current.txt
+++ b/autofill/autofill/api/current.txt
@@ -156,6 +156,7 @@
   public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
     method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+    method public int getLayoutDirection();
     method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
     method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+    method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt b/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt
+++ b/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt
@@ -156,6 +156,7 @@
   public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
     method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+    method public int getLayoutDirection();
     method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
     method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+    method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/public_plus_experimental_current.txt b/autofill/autofill/api/public_plus_experimental_current.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/public_plus_experimental_current.txt
+++ b/autofill/autofill/api/public_plus_experimental_current.txt
@@ -156,6 +156,7 @@
   public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
     method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+    method public int getLayoutDirection();
     method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
     method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+    method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/restricted_1.1.0-alpha02.txt b/autofill/autofill/api/restricted_1.1.0-alpha02.txt
index 79e5e66..78c7008 100644
--- a/autofill/autofill/api/restricted_1.1.0-alpha02.txt
+++ b/autofill/autofill/api/restricted_1.1.0-alpha02.txt
@@ -159,6 +159,7 @@
   public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
     method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+    method public int getLayoutDirection();
     method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
     method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -170,6 +171,7 @@
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+    method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/restricted_current.txt b/autofill/autofill/api/restricted_current.txt
index 79e5e66..78c7008 100644
--- a/autofill/autofill/api/restricted_current.txt
+++ b/autofill/autofill/api/restricted_current.txt
@@ -159,6 +159,7 @@
   public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
     method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+    method public int getLayoutDirection();
     method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
     method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
     method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -170,6 +171,7 @@
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+    method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
     method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/src/androidTest/AndroidManifest.xml b/autofill/autofill/src/androidTest/AndroidManifest.xml
index 966f635..a7bf090 100644
--- a/autofill/autofill/src/androidTest/AndroidManifest.xml
+++ b/autofill/autofill/src/androidTest/AndroidManifest.xml
@@ -14,8 +14,10 @@
   limitations under the License
   -->
 
-<manifest package="androidx.autofill.tests">
-    <application>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.autofill.tests">
+    <application
+        android:supportsRtl="true">
         <activity xmlns:android="http://schemas.android.com/apk/res/android"
             android:name="androidx.autofill.inline.InlineUiActivity">
         </activity>
diff --git a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java
index 29c7d6b..7f8df02 100644
--- a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java
+++ b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java
@@ -99,4 +99,18 @@
         // When both background and background color are set, the background color takes precedence.
         TestUtils.verifyBackgroundColor(view, Color.YELLOW);
     }
+
+    @Test
+    public void testStyleWithRtl() {
+        ViewStyle.Builder builder = new ViewStyle.Builder();
+        ViewStyle style = builder
+                .setPadding(1, 2, 3, 4)
+                .setLayoutMargin(5, 6, 7, 8)
+                .build();
+        View view = new View(mContext);
+        view.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+        style.applyStyleOnViewIfValid(view);
+        TestUtils.verifyPadding(view, 3, 2, 1, 4);
+        TestUtils.verifyLayoutMargin(view, 7, 6, 5, 8);
+    }
 }
diff --git a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java
index bb7e554..78a2d4f 100644
--- a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java
+++ b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java
@@ -225,7 +225,6 @@
         assertEquals(TITLE, titleView.getText());
         assertEquals(Color.BLUE, titleView.getCurrentTextColor());
 
-
         TextView subtitleView =
                 mLinearLayout.findViewById(R.id.autofill_inline_suggestion_subtitle);
         assertEquals(SUB_TITLE, subtitleView.getText());
@@ -239,6 +238,72 @@
         TestUtils.verifyPadding(endIcon, 21, 22, 23, 24);
     }
 
+    @Test
+    public void testRender_allWidgets_rtl() {
+        InlineSuggestionUi.Style style = new InlineSuggestionUi.Style.Builder()
+                .setLayoutDirection(View.LAYOUT_DIRECTION_RTL)
+                .setChipStyle(new ViewStyle.Builder().setPadding(11, 12, 13, 14).build())
+                .setStartIconStyle(new ImageViewStyle.Builder()
+                        .setPadding(21, 22, 23, 24)
+                        .setLayoutMargin(31, 32, 33, 34).build())
+                .setSingleIconChipStyle(new ViewStyle.Builder().setPadding(41, 42, 43, 44).build())
+                .setSingleIconChipIconStyle(new ImageViewStyle.Builder()
+                        .setPadding(51, 52, 53, 54)
+                        .setLayoutMargin(61, 62, 63, 64).build())
+                .build();
+        InlineSuggestionUi.Content contentAllWidgets = InlineSuggestionUi.newContentBuilder(
+                mAttributionIntent)
+                .setContentDescription("Content blabla")
+                .setTitle(TITLE)
+                .setSubtitle(SUB_TITLE)
+                .setStartIcon(Icon.createWithResource(mContext,
+                        androidx.autofill.test.R.drawable.ic_settings))
+                .setEndIcon(Icon.createWithResource(mContext,
+                        androidx.autofill.test.R.drawable.ic_settings)).build();
+        View view = InlineSuggestionUi.render(mContext, contentAllWidgets, style);
+        addView(view);
+
+        verifyVisibility(true, true, true, true);
+        TestUtils.verifyPadding(view, 13, 12, 11, 14);
+        assertEquals("Content blabla", view.getContentDescription());
+
+        ImageView startIcon =
+                mLinearLayout.findViewById(R.id.autofill_inline_suggestion_start_icon);
+        TestUtils.verifyPadding(startIcon, 23, 22, 21, 24);
+        TestUtils.verifyLayoutMargin(startIcon, 33, 32, 31, 34);
+    }
+
+    @Test
+    public void testRender_singleIcon_rtl() {
+        InlineSuggestionUi.Style style = new InlineSuggestionUi.Style.Builder()
+                .setLayoutDirection(View.LAYOUT_DIRECTION_RTL)
+                .setChipStyle(new ViewStyle.Builder().setPadding(11, 12, 13, 14).build())
+                .setStartIconStyle(new ImageViewStyle.Builder()
+                        .setPadding(21, 22, 23, 24)
+                        .setLayoutMargin(31, 32, 33, 34).build())
+                .setSingleIconChipStyle(new ViewStyle.Builder().setPadding(41, 42, 43, 44).build())
+                .setSingleIconChipIconStyle(new ImageViewStyle.Builder()
+                        .setPadding(51, 52, 53, 54)
+                        .setLayoutMargin(61, 62, 63, 64).build())
+                .build();
+        InlineSuggestionUi.Content contentSingleIcon = InlineSuggestionUi.newContentBuilder(
+                mAttributionIntent)
+                .setContentDescription("Content blabla")
+                .setStartIcon(Icon.createWithResource(mContext,
+                        androidx.autofill.test.R.drawable.ic_settings)).build();
+        View view = InlineSuggestionUi.render(mContext, contentSingleIcon, style);
+        addView(view);
+
+        verifyVisibility(false, false, true, false);
+        TestUtils.verifyPadding(view, 43, 42, 41, 44);
+        assertEquals("Content blabla", view.getContentDescription());
+
+        ImageView startIcon =
+                mLinearLayout.findViewById(R.id.autofill_inline_suggestion_start_icon);
+        TestUtils.verifyPadding(startIcon, 53, 52, 51, 54);
+        TestUtils.verifyLayoutMargin(startIcon, 63, 62, 61, 64);
+    }
+
     /** Below are tests for the Content class */
 
     @Test
@@ -397,6 +462,35 @@
         TestUtils.verifyBackgroundColor(endIconView, Color.RED);
     }
 
+    @Test
+    public void testStyleWithRtl() {
+        InlineSuggestionUi.Style.Builder builder = new InlineSuggestionUi.Style.Builder();
+        InlineSuggestionUi.Style style = builder.setLayoutDirection(
+                View.LAYOUT_DIRECTION_RTL).build();
+
+        View suggestionView = LayoutInflater.from(mContext).inflate(
+                R.layout.autofill_inline_suggestion, null);
+        ImageView startIconView = suggestionView.findViewById(
+                R.id.autofill_inline_suggestion_start_icon);
+        startIconView.setVisibility(View.VISIBLE);
+        TextView titleView = suggestionView.findViewById(R.id.autofill_inline_suggestion_title);
+        titleView.setVisibility(View.VISIBLE);
+        TextView subtitleView = suggestionView.findViewById(
+                R.id.autofill_inline_suggestion_subtitle);
+        subtitleView.setVisibility(View.VISIBLE);
+        ImageView endIconView = suggestionView.findViewById(
+                R.id.autofill_inline_suggestion_end_icon);
+        endIconView.setVisibility(View.VISIBLE);
+
+        style.applyStyle(suggestionView, startIconView, titleView, subtitleView, endIconView);
+
+        assertEquals(View.LAYOUT_DIRECTION_RTL, suggestionView.getLayoutDirection());
+        assertEquals(View.LAYOUT_DIRECTION_RTL, startIconView.getLayoutDirection());
+        assertEquals(View.LAYOUT_DIRECTION_RTL, titleView.getLayoutDirection());
+        assertEquals(View.LAYOUT_DIRECTION_RTL, subtitleView.getLayoutDirection());
+        assertEquals(View.LAYOUT_DIRECTION_RTL, endIconView.getLayoutDirection());
+    }
+
     /** Below are private helper methods */
 
     private void addView(View view) {
diff --git a/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java b/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java
index 42b40c4..a47c354 100644
--- a/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java
+++ b/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java
@@ -80,7 +80,11 @@
         if (mBundle.containsKey(KEY_PADDING)) {
             int[] padding = mBundle.getIntArray(KEY_PADDING);
             if (padding != null && padding.length == 4) {
-                view.setPadding(padding[0], padding[1], padding[2], padding[3]);
+                if (view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+                    view.setPadding(padding[0], padding[1], padding[2], padding[3]);
+                } else {
+                    view.setPadding(padding[2], padding[1], padding[0], padding[3]);
+                }
             }
         }
         if (mBundle.containsKey(KEY_LAYOUT_MARGIN)) {
@@ -94,9 +98,16 @@
                 } else if (!(layoutParams instanceof ViewGroup.MarginLayoutParams)) {
                     layoutParams = new ViewGroup.MarginLayoutParams(layoutParams);
                 }
-                ((ViewGroup.MarginLayoutParams) layoutParams).setMargins(layoutMargin[0],
-                        layoutMargin[1], layoutMargin[2], layoutMargin[3]);
-                view.setLayoutParams(layoutParams);
+                ViewGroup.MarginLayoutParams marginLayoutParams =
+                        (ViewGroup.MarginLayoutParams) layoutParams;
+                if (view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+                    marginLayoutParams.setMargins(layoutMargin[0],
+                            layoutMargin[1], layoutMargin[2], layoutMargin[3]);
+                } else {
+                    marginLayoutParams.setMargins(layoutMargin[2],
+                            layoutMargin[1], layoutMargin[0], layoutMargin[3]);
+                }
+                view.setLayoutParams(marginLayoutParams);
             }
         }
     }
@@ -163,32 +174,38 @@
         /**
          * Sets the padding.
          *
-         * @param left   the left padding in pixels
+         * <p> Note that the method takes start/end rather than left/right, respecting the layout
+         * direction.
+         *
+         * @param start   the start padding in pixels
          * @param top    the top padding in pixels
-         * @param right  the right padding in pixels
+         * @param end  the end padding in pixels
          * @param bottom the bottom padding in pixels
          * @see android.view.View#setPadding(int, int, int, int)
          */
         @NonNull
-        public B setPadding(int left, int top, int right, int bottom) {
-            mBundle.putIntArray(KEY_PADDING, new int[]{left, top, right, bottom});
+        public B setPadding(int start, int top, int end, int bottom) {
+            mBundle.putIntArray(KEY_PADDING, new int[]{start, top, end, bottom});
             return getThis();
         }
 
         /**
          * Sets the layout margin through the view's layout param.
          *
-         * @param left   the left margin size
+         * <p> Note that the method takes start/end rather than left/right, respecting the layout
+         * direction.
+         *
+         * @param start   the start margin size
          * @param top    the top margin size
-         * @param right  the right margin size
+         * @param end  the end margin size
          * @param bottom the bottom margin size
          * @see android.view.ViewGroup.MarginLayoutParams#setMargins(int, int, int, int)
          * @see android.view.View#setLayoutParams(android.view.ViewGroup.LayoutParams)
          */
         @NonNull
-        public B setLayoutMargin(int left, int top, int right,
+        public B setLayoutMargin(int start, int top, int end,
                 int bottom) {
-            mBundle.putIntArray(KEY_LAYOUT_MARGIN, new int[]{left, top, right, bottom});
+            mBundle.putIntArray(KEY_LAYOUT_MARGIN, new int[]{start, top, end, bottom});
             return getThis();
         }
     }
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 0d2965a..6d4adc9 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
@@ -210,6 +210,7 @@
         private static final String KEY_END_ICON_STYLE = "end_icon_style";
         private static final String KEY_SINGLE_ICON_CHIP_STYLE = "single_icon_chip_style";
         private static final String KEY_SINGLE_ICON_CHIP_ICON_STYLE = "single_icon_chip_icon_style";
+        private static final String KEY_LAYOUT_DIRECTION = "layout_direction";
 
         /**
          * Use {@link InlineSuggestionUi#fromBundle(Bundle)} or {@link Builder#build()} to
@@ -238,6 +239,10 @@
             if (!isValid()) {
                 return;
             }
+
+            // layout direction
+            singleIconChipView.setLayoutDirection(getLayoutDirection());
+
             // single icon
             if (singleIconView.getVisibility() != View.GONE) {
                 ImageViewStyle singleIconViewStyle = getSingleIconChipIconStyle();
@@ -268,6 +273,10 @@
             if (!isValid()) {
                 return;
             }
+
+            // layout direction
+            chipView.setLayoutDirection(getLayoutDirection());
+
             // start icon
             if (startIconView.getVisibility() != View.GONE) {
                 ImageViewStyle startIconViewStyle = getStartIconStyle();
@@ -313,6 +322,17 @@
             return UiVersions.INLINE_UI_VERSION_1;
         }
 
+        /**
+         * @see Builder#setLayoutDirection(int)
+         */
+        public int getLayoutDirection() {
+            int layoutDirection = mBundle.getInt(KEY_LAYOUT_DIRECTION, View.LAYOUT_DIRECTION_LTR);
+            if (layoutDirection != View.LAYOUT_DIRECTION_LTR
+                    && layoutDirection != View.LAYOUT_DIRECTION_RTL) {
+                layoutDirection = View.LAYOUT_DIRECTION_LTR;
+            }
+            return layoutDirection;
+        }
 
         /**
          * @see Builder#setChipStyle(ViewStyle)
@@ -390,6 +410,24 @@
             }
 
             /**
+             * Sets the layout direction for the UI.
+             *
+             * <p>Note that the process that renders the UI needs to have
+             * {@code android:supportsRtl="true"} for this to take effect.
+             *
+             * @param layoutDirection the layout direction to set. Should be one of:
+             *                        {@link View#LAYOUT_DIRECTION_LTR},
+             *                        {@link View#LAYOUT_DIRECTION_RTL}.
+             *
+             * @see View#setLayoutDirection(int)
+             */
+            @NonNull
+            public Builder setLayoutDirection(int layoutDirection) {
+                mBundle.putInt(KEY_LAYOUT_DIRECTION, layoutDirection);
+                return this;
+            }
+
+            /**
              * Sets the chip style.
              *
              * <p>See {@link #setSingleIconChipStyle(ViewStyle)} for more information about setting
diff --git a/autofill/autofill/src/main/res/values/dimens.xml b/autofill/autofill/src/main/res/values/dimens.xml
index 257c7ed..2cbe67a 100644
--- a/autofill/autofill/src/main/res/values/dimens.xml
+++ b/autofill/autofill/src/main/res/values/dimens.xml
@@ -17,5 +17,4 @@
 
 <resources>
     <dimen name="autofill_inline_suggestion_icon_size">20dp</dimen>
-    <dimen name="autofill_inline_suggestion_single_icon_size">24dp</dimen>
 </resources>
diff --git a/autofill/autofill/src/main/res/values/styles.xml b/autofill/autofill/src/main/res/values/styles.xml
index f0601bd..a986979 100644
--- a/autofill/autofill/src/main/res/values/styles.xml
+++ b/autofill/autofill/src/main/res/values/styles.xml
@@ -21,7 +21,9 @@
 
     <style name="Widget.Autofill.InlineSuggestionChip">
         <item name="android:background">@drawable/autofill_inline_suggestion_chip_background</item>
+        <item name="android:paddingStart">13dp</item>
         <item name="android:paddingLeft">13dp</item>
+        <item name="android:paddingEnd">13dp</item>
         <item name="android:paddingRight">13dp</item>
     </style>
 
@@ -35,7 +37,9 @@
         <item name="android:textColor">#FF202124</item>
         <item name="android:textSize">16sp</item>
         <item name="android:typeface">sans</item>
+        <item name="android:layout_marginStart">4dp</item>
         <item name="android:layout_marginLeft">4dp</item>
+        <item name="android:layout_marginEnd">4dp</item>
         <item name="android:layout_marginRight">4dp</item>
     </style>
 
@@ -43,6 +47,7 @@
         <item name="android:textColor">#99202124</item>
         <item name="android:textSize">14sp</item>
         <item name="android:typeface">sans</item>
+        <item name="android:layout_marginEnd">4dp</item>
         <item name="android:layout_marginRight">4dp</item>
     </style>
 
diff --git a/benchmark/benchmark/src/androidTest/AndroidManifest.xml b/benchmark/benchmark/src/androidTest/AndroidManifest.xml
index 82470db..b20d8c1 100644
--- a/benchmark/benchmark/src/androidTest/AndroidManifest.xml
+++ b/benchmark/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
diff --git a/benchmark/common/api/1.1.0-alpha01.txt b/benchmark/common/api/1.1.0-alpha01.txt
index 291b7b8..4f7ae83 100644
--- a/benchmark/common/api/1.1.0-alpha01.txt
+++ b/benchmark/common/api/1.1.0-alpha01.txt
@@ -8,7 +8,7 @@
     method public boolean keepRunning();
     method public void pauseTiming();
     method public void resumeTiming();
-    field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
   }
 
   public static final class BenchmarkState.Companion {
diff --git a/benchmark/common/api/1.1.0-alpha02.ignore b/benchmark/common/api/1.1.0-alpha02.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/1.1.0-alpha02.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+    Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/1.1.0-alpha02.txt b/benchmark/common/api/1.1.0-alpha02.txt
new file mode 100644
index 0000000..8e0fdce
--- /dev/null
+++ b/benchmark/common/api/1.1.0-alpha02.txt
@@ -0,0 +1,21 @@
+// Signature format: 3.0
+package androidx.benchmark {
+
+  public final class ArgumentsKt {
+  }
+
+  public final class BenchmarkState {
+    method public boolean keepRunning();
+    method public void pauseTiming();
+    method public void resumeTiming();
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+  }
+
+  public static final class BenchmarkState.Companion {
+  }
+
+  public final class MetricNameUtilsKt {
+  }
+
+}
+
diff --git a/benchmark/common/api/current.txt b/benchmark/common/api/current.txt
index 291b7b8..8e0fdce 100644
--- a/benchmark/common/api/current.txt
+++ b/benchmark/common/api/current.txt
@@ -8,15 +8,12 @@
     method public boolean keepRunning();
     method public void pauseTiming();
     method public void resumeTiming();
-    field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
   }
 
   public static final class BenchmarkState.Companion {
   }
 
-  public final class IdeOutputKt {
-  }
-
   public final class MetricNameUtilsKt {
   }
 
diff --git a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
index 4aaaeed..80824a4 100644
--- a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
+++ b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
@@ -11,7 +11,7 @@
     method public void pauseTiming();
     method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
     method public void resumeTiming();
-    field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
   }
 
   public static final class BenchmarkState.Companion {
diff --git a/benchmark/common/api/public_plus_experimental_1.1.0-alpha02.txt b/benchmark/common/api/public_plus_experimental_1.1.0-alpha02.txt
new file mode 100644
index 0000000..fc72f89
--- /dev/null
+++ b/benchmark/common/api/public_plus_experimental_1.1.0-alpha02.txt
@@ -0,0 +1,28 @@
+// Signature format: 3.0
+package androidx.benchmark {
+
+  public final class ArgumentsKt {
+  }
+
+  public final class BenchmarkState {
+    ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public BenchmarkState();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public long getMinTimeNanos();
+    method public boolean keepRunning();
+    method public void pauseTiming();
+    method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
+    method public void resumeTiming();
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+  }
+
+  public static final class BenchmarkState.Companion {
+    method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
+  }
+
+  @kotlin.Experimental @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
+  }
+
+  public final class MetricNameUtilsKt {
+  }
+
+}
+
diff --git a/benchmark/common/api/public_plus_experimental_current.txt b/benchmark/common/api/public_plus_experimental_current.txt
index 4aaaeed..fc72f89 100644
--- a/benchmark/common/api/public_plus_experimental_current.txt
+++ b/benchmark/common/api/public_plus_experimental_current.txt
@@ -11,7 +11,7 @@
     method public void pauseTiming();
     method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
     method public void resumeTiming();
-    field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
   }
 
   public static final class BenchmarkState.Companion {
@@ -21,9 +21,6 @@
   @kotlin.Experimental @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
   }
 
-  public final class IdeOutputKt {
-  }
-
   public final class MetricNameUtilsKt {
   }
 
diff --git a/benchmark/common/api/res-1.1.0-alpha02.txt b/benchmark/common/api/res-1.1.0-alpha02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/common/api/res-1.1.0-alpha02.txt
diff --git a/benchmark/common/api/restricted_1.1.0-alpha01.txt b/benchmark/common/api/restricted_1.1.0-alpha01.txt
index a91c3dc..c39c72d3 100644
--- a/benchmark/common/api/restricted_1.1.0-alpha01.txt
+++ b/benchmark/common/api/restricted_1.1.0-alpha01.txt
@@ -9,7 +9,7 @@
     method @kotlin.PublishedApi internal boolean keepRunningInternal();
     method public void pauseTiming();
     method public void resumeTiming();
-    field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
     field @kotlin.PublishedApi internal int iterationsRemaining;
   }
 
diff --git a/benchmark/common/api/restricted_1.1.0-alpha02.ignore b/benchmark/common/api/restricted_1.1.0-alpha02.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/restricted_1.1.0-alpha02.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+    Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/restricted_1.1.0-alpha02.txt b/benchmark/common/api/restricted_1.1.0-alpha02.txt
new file mode 100644
index 0000000..5c18529
--- /dev/null
+++ b/benchmark/common/api/restricted_1.1.0-alpha02.txt
@@ -0,0 +1,23 @@
+// Signature format: 3.0
+package androidx.benchmark {
+
+  public final class ArgumentsKt {
+  }
+
+  public final class BenchmarkState {
+    method public boolean keepRunning();
+    method @kotlin.PublishedApi internal boolean keepRunningInternal();
+    method public void pauseTiming();
+    method public void resumeTiming();
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+    field @kotlin.PublishedApi internal int iterationsRemaining;
+  }
+
+  public static final class BenchmarkState.Companion {
+  }
+
+  public final class MetricNameUtilsKt {
+  }
+
+}
+
diff --git a/benchmark/common/api/restricted_current.txt b/benchmark/common/api/restricted_current.txt
index a91c3dc..5c18529 100644
--- a/benchmark/common/api/restricted_current.txt
+++ b/benchmark/common/api/restricted_current.txt
@@ -9,16 +9,13 @@
     method @kotlin.PublishedApi internal boolean keepRunningInternal();
     method public void pauseTiming();
     method public void resumeTiming();
-    field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+    field public static final androidx.benchmark.BenchmarkState.Companion Companion;
     field @kotlin.PublishedApi internal int iterationsRemaining;
   }
 
   public static final class BenchmarkState.Companion {
   }
 
-  public final class IdeOutputKt {
-  }
-
   public final class MetricNameUtilsKt {
   }
 
diff --git a/benchmark/common/src/androidTest/java/androidx/benchmark/IdeOutputTest.kt b/benchmark/common/src/androidTest/java/androidx/benchmark/InstrumentationResultsTest.kt
similarity index 78%
rename from benchmark/common/src/androidTest/java/androidx/benchmark/IdeOutputTest.kt
rename to benchmark/common/src/androidTest/java/androidx/benchmark/InstrumentationResultsTest.kt
index e0209ad..a435e31 100644
--- a/benchmark/common/src/androidTest/java/androidx/benchmark/IdeOutputTest.kt
+++ b/benchmark/common/src/androidTest/java/androidx/benchmark/InstrumentationResultsTest.kt
@@ -24,11 +24,11 @@
 
 @SmallTest
 @RunWith(JUnit4::class)
-class IdeOutputTest {
+class InstrumentationResultsTest {
     @Test
     fun ideSummary_alignment() {
-        val summary1 = ideSummaryLine("foo", 1000, 100)
-        val summary2 = ideSummaryLine("fooBarLongerKey", 10000, 0)
+        val summary1 = InstrumentationResults.ideSummaryLine("foo", 1000, 100)
+        val summary2 = InstrumentationResults.ideSummaryLine("fooBarLongerKey", 10000, 0)
 
         assertEquals(
             summary1.indexOf("foo"),
@@ -40,11 +40,11 @@
     fun ideSummary_allocs() {
         assertEquals(
             "        1,000 ns    foo",
-            ideSummaryLine("foo", 1000, null)
+            InstrumentationResults.ideSummaryLine("foo", 1000, null)
         )
         assertEquals(
             "        1,000 ns          10 allocs    foo",
-            ideSummaryLine("foo", 1000, 10)
+            InstrumentationResults.ideSummaryLine("foo", 1000, 10)
         )
     }
 }
\ No newline at end of file
diff --git a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
index c1abfdf..d308221 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
@@ -25,7 +25,6 @@
 import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
 import androidx.benchmark.Errors.PREFIX
-import androidx.test.platform.app.InstrumentationRegistry
 import androidx.tracing.Trace
 import java.io.File
 import java.util.concurrent.TimeUnit
@@ -217,6 +216,7 @@
                 ).absolutePath
 
                 Log.d(TAG, "Profiling output file: $path")
+                InstrumentationResults.reportAdditionalFileToCopy("profiling_trace", path)
 
                 val bufferSize = 16 * 1024 * 1024
                 if (Arguments.profilingMode == ProfilingMode.Sampled &&
@@ -528,10 +528,12 @@
             // these 'legacy' CI output stats are considered output
             stats.forEach { it.putInBundle(status, PREFIX) }
         }
-        status.putIdeSummaryLine(
-            testName = key,
-            nanos = getMinTimeNanos(),
-            allocations = stats.firstOrNull { it.name == "allocationCount" }?.median
+        status.putAll(
+            InstrumentationResults.getIdeSummaryLine(
+                testName = key,
+                nanos = getMinTimeNanos(),
+                allocations = stats.firstOrNull { it.name == "allocationCount" }?.median
+            )
         )
         return status
     }
@@ -560,8 +562,9 @@
         checkState() // this method is triggered externally
         val fullTestName = "$PREFIX$simpleClassName.$methodName"
 
-        val bundle = getFullStatusReport(key = fullTestName, includeStats = !Arguments.dryRunMode)
-        reportBundle(bundle)
+        InstrumentationResults.report(
+            getFullStatusReport(key = fullTestName, includeStats = !Arguments.dryRunMode)
+        )
 
         ResultWriter.appendReport(
             getReport(
@@ -659,30 +662,18 @@
                 warmupIterations = warmupIterations
             )
             // Report value to Studio console
-            val bundle = Bundle()
             val fullTestName = PREFIX +
                     if (className.isNotEmpty()) "$className.$testName" else testName
-            bundle.putIdeSummaryLine(
-                testName = fullTestName,
-                nanos = report.getStats("timeNs").min,
-                allocations = null
+            InstrumentationResults.report(
+                InstrumentationResults.getIdeSummaryLine(
+                    testName = fullTestName,
+                    nanos = report.getStats("timeNs").min,
+                    allocations = null
+                )
             )
-            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/common/src/main/java/androidx/benchmark/IdeOutput.kt b/benchmark/common/src/main/java/androidx/benchmark/IdeOutput.kt
deleted file mode 100644
index 7146f5b..0000000
--- a/benchmark/common/src/main/java/androidx/benchmark/IdeOutput.kt
+++ /dev/null
@@ -1,56 +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.benchmark
-
-import android.os.Bundle
-import java.text.NumberFormat
-
-private const val STUDIO_OUTPUT_KEY_PREFIX = "android.studio.display."
-private const val STUDIO_OUTPUT_KEY_ID = "benchmark"
-
-private fun ideSummaryLineWrapped(key: String, nanos: Long, allocations: Long?): String {
-    val warningLines =
-        Errors.acquireWarningStringForLogging()?.split("\n") ?: listOf()
-    return (warningLines + ideSummaryLine(key, nanos, allocations))
-        // remove first line if empty
-        .filterIndexed { index, it -> index != 0 || it.isNotEmpty() }
-        // join, prepending key to everything but first string,
-        // to make each line look the same
-        .joinToString("\n$STUDIO_OUTPUT_KEY_ID: ")
-}
-
-// NOTE: this summary line will use default locale to determine separators. As
-// this line is only meant for human eyes, we don't worry about consistency here.
-internal fun ideSummaryLine(key: String, nanos: Long, allocations: Long?): String {
-    val numberFormat = NumberFormat.getNumberInstance()
-    return listOfNotNull(
-        // 13 alignment is enough for ~10 seconds
-        "%13s ns".format(numberFormat.format(nanos)),
-        // 9 alignment is enough for ~10 million allocations
-        allocations?.run {
-            "%8s allocs".format(numberFormat.format(allocations))
-        },
-        key
-    ).joinToString("    ")
-}
-
-internal fun Bundle.putIdeSummaryLine(testName: String, nanos: Long, allocations: Long?) {
-    putString(
-        STUDIO_OUTPUT_KEY_PREFIX + STUDIO_OUTPUT_KEY_ID,
-        ideSummaryLineWrapped(testName, nanos, allocations)
-    )
-}
\ No newline at end of file
diff --git a/benchmark/common/src/main/java/androidx/benchmark/InstrumentationResults.kt b/benchmark/common/src/main/java/androidx/benchmark/InstrumentationResults.kt
new file mode 100644
index 0000000..436735a
--- /dev/null
+++ b/benchmark/common/src/main/java/androidx/benchmark/InstrumentationResults.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.benchmark
+
+import android.os.Bundle
+import androidx.test.platform.app.InstrumentationRegistry
+import java.text.NumberFormat
+
+/**
+ * Provides way to report additional results via `Instrumentation.sendStatus()` / `addResult()`.
+ */
+internal object InstrumentationResults {
+    private const val STUDIO_OUTPUT_KEY_PREFIX = "android.studio.display."
+    private const val STUDIO_OUTPUT_KEY_ID = "benchmark"
+
+    private const val ADDITIONAL_FILE_OUTPUT_KEY_PREFIX = "additionalTestOutputFile_"
+
+    private fun ideSummaryLineWrapped(key: String, nanos: Long, allocations: Long?): String {
+        val warningLines =
+            Errors.acquireWarningStringForLogging()?.split("\n") ?: listOf()
+        return (warningLines + ideSummaryLine(key, nanos, allocations))
+            // remove first line if empty
+            .filterIndexed { index, it -> index != 0 || it.isNotBlank() }
+            // join, prepending key to everything but first string,
+            // to make each line look the same
+            .joinToString("\n$STUDIO_OUTPUT_KEY_ID: ")
+    }
+
+    // NOTE: this summary line will use default locale to determine separators. As
+    // this line is only meant for human eyes, we don't worry about consistency here.
+    internal fun ideSummaryLine(key: String, nanos: Long, allocations: Long?): String {
+        val numberFormat = NumberFormat.getNumberInstance()
+        return listOfNotNull(
+            // 13 alignment is enough for ~10 seconds
+            "%13s ns".format(numberFormat.format(nanos)),
+            // 9 alignment is enough for ~10 million allocations
+            allocations?.run {
+                "%8s allocs".format(numberFormat.format(allocations))
+            },
+            key
+        ).joinToString("    ")
+    }
+
+    internal fun getIdeSummaryLine(testName: String, nanos: Long, allocations: Long?) =
+        Bundle().also {
+            it.putString(
+                STUDIO_OUTPUT_KEY_PREFIX + STUDIO_OUTPUT_KEY_ID,
+                ideSummaryLineWrapped(testName, nanos, allocations)
+            )
+        }
+
+    internal fun reportAdditionalFileToCopy(key: String, absoluteFilePath: String) {
+        reportBundle(Bundle().also {
+            it.putString(ADDITIONAL_FILE_OUTPUT_KEY_PREFIX + key, absoluteFilePath)
+        })
+    }
+
+    internal fun report(bundle: Bundle) {
+        reportBundle(bundle)
+    }
+
+    /**
+     * 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
+     */
+    private fun reportBundle(bundle: Bundle) {
+        InstrumentationRegistry
+            .getInstrumentation()
+            .sendStatus(2, bundle)
+    }
+}
\ No newline at end of file
diff --git a/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt b/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt
index c61d8f9..7505146 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt
@@ -38,6 +38,7 @@
 
             val file = File(Arguments.testOutputDir, "$packageName-benchmarkData.json")
             writeReport(file, reports)
+            InstrumentationResults.reportAdditionalFileToCopy("results_json", file.absolutePath)
         }
     }
 
diff --git a/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml b/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml
index 6434fda..3362f60 100644
--- a/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml
+++ b/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml
@@ -19,9 +19,12 @@
     xmlns:tools="http://schemas.android.com/tools"
     package="androidx.benchmark.integration.startup.benchmark.test">
     <application
-        android:name="androidx.benchmark.integration.startup.benchmark.ArgumentInjectingApplication"
-        android:debuggable="false"
-        tools:ignore="HardcodedDebugMode"
-        tools:replace="android:debuggable" />
-    />
+            android:name="androidx.benchmark.integration.startup.benchmark.ArgumentInjectingApplication"
+            android:debuggable="false"
+            tools:ignore="HardcodedDebugMode"
+            tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable shell="true"/>
+    </application>
 </manifest>
diff --git a/benchmark/junit4/api/1.1.0-alpha02.txt b/benchmark/junit4/api/1.1.0-alpha02.txt
new file mode 100644
index 0000000..34ad6a658
--- /dev/null
+++ b/benchmark/junit4/api/1.1.0-alpha02.txt
@@ -0,0 +1,23 @@
+// Signature format: 3.0
+package androidx.benchmark.junit4 {
+
+  public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+    ctor public AndroidBenchmarkRunner();
+  }
+
+  public final class BenchmarkRule implements org.junit.rules.TestRule {
+    ctor public BenchmarkRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public androidx.benchmark.BenchmarkState getState();
+  }
+
+  public final class BenchmarkRule.Scope {
+    method public inline <T> T! runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+  public final class BenchmarkRuleKt {
+    method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+  }
+
+}
+
diff --git a/benchmark/junit4/api/public_plus_experimental_1.1.0-alpha02.txt b/benchmark/junit4/api/public_plus_experimental_1.1.0-alpha02.txt
new file mode 100644
index 0000000..34ad6a658
--- /dev/null
+++ b/benchmark/junit4/api/public_plus_experimental_1.1.0-alpha02.txt
@@ -0,0 +1,23 @@
+// Signature format: 3.0
+package androidx.benchmark.junit4 {
+
+  public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+    ctor public AndroidBenchmarkRunner();
+  }
+
+  public final class BenchmarkRule implements org.junit.rules.TestRule {
+    ctor public BenchmarkRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public androidx.benchmark.BenchmarkState getState();
+  }
+
+  public final class BenchmarkRule.Scope {
+    method public inline <T> T! runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+  public final class BenchmarkRuleKt {
+    method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+  }
+
+}
+
diff --git a/benchmark/junit4/api/res-1.1.0-alpha02.txt b/benchmark/junit4/api/res-1.1.0-alpha02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/junit4/api/res-1.1.0-alpha02.txt
diff --git a/benchmark/junit4/api/restricted_1.1.0-alpha02.txt b/benchmark/junit4/api/restricted_1.1.0-alpha02.txt
new file mode 100644
index 0000000..ac47d85
--- /dev/null
+++ b/benchmark/junit4/api/restricted_1.1.0-alpha02.txt
@@ -0,0 +1,24 @@
+// Signature format: 3.0
+package androidx.benchmark.junit4 {
+
+  public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+    ctor public AndroidBenchmarkRunner();
+  }
+
+  public final class BenchmarkRule implements org.junit.rules.TestRule {
+    ctor public BenchmarkRule();
+    method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+    method public androidx.benchmark.BenchmarkState getState();
+  }
+
+  public final class BenchmarkRule.Scope {
+    method @kotlin.PublishedApi internal androidx.benchmark.BenchmarkState getOuterState();
+    method public inline <T> T! runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+  public final class BenchmarkRuleKt {
+    method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+  }
+
+}
+
diff --git a/browser/browser/api/api_lint.ignore b/browser/browser/api/api_lint.ignore
index a4d5f5e..0a088b5 100644
--- a/browser/browser/api/api_lint.ignore
+++ b/browser/browser/api/api_lint.ignore
@@ -57,8 +57,6 @@
     Must avoid boxed primitives (`java.lang.Integer`)
 
 
-BuilderSetStyle: androidx.browser.customtabs.CustomTabsIntent.Builder#enableUrlBarHiding():
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.browser.customtabs.CustomTabsIntent.Builder.enableUrlBarHiding()
 BuilderSetStyle: androidx.browser.trusted.TrustedWebActivityIntentBuilder#buildCustomTabsIntent():
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.browser.trusted.TrustedWebActivityIntentBuilder.buildCustomTabsIntent()
 
@@ -79,7 +77,7 @@
     Listeners should always be at end of argument list (method `newSession`)
 
 
-OptionalBuilderConstructorAgrument: androidx.browser.customtabs.CustomTabsIntent.Builder#Builder(androidx.browser.customtabs.CustomTabsSession) parameter #0:
+OptionalBuilderConstructorArgument: androidx.browser.customtabs.CustomTabsIntent.Builder#Builder(androidx.browser.customtabs.CustomTabsSession) parameter #0:
     Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter session in androidx.browser.customtabs.CustomTabsIntent.Builder(androidx.browser.customtabs.CustomTabsSession session)
 
 
diff --git a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
index b0e39b7..c415c6b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
@@ -136,6 +136,7 @@
             "-Xep:ParameterName:ERROR",
             "-Xep:RxReturnValueIgnored:ERROR",
             "-Xep:BadImport:ERROR",
+            "-Xep:MissingCasesInEnumSwitch:ERROR",
 
             // Nullaway
             "-XepIgnoreUnknownCheckNames", // https://github.com/uber/NullAway/issues/25
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 59fd81d..34252fe 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -31,7 +31,7 @@
     val ARCH_RUNTIME = Version("2.2.0-alpha01")
     val ASYNCLAYOUTINFLATER = Version("1.1.0-alpha01")
     val AUTOFILL = Version("1.1.0-alpha02")
-    val BENCHMARK = Version("1.1.0-alpha01")
+    val BENCHMARK = Version("1.1.0-alpha02")
     val BIOMETRIC = Version("1.1.0-alpha01")
     val BROWSER = Version("1.3.0-alpha04")
     val BUILDSRC_TESTS = Version("1.0.0-alpha01")
@@ -79,7 +79,7 @@
     val MEDIA2 = Version("1.1.0-alpha01")
     val MEDIAROUTER = Version("1.2.0-alpha01")
     val NAVIGATION = Version("2.4.0-alpha01")
-    val PAGING = Version("3.0.0-alpha02")
+    val PAGING = Version("3.0.0-alpha03")
     val PALETTE = Version("1.1.0-alpha01")
     val PRINT = Version("1.1.0-alpha01")
     val PERCENTLAYOUT = Version("1.1.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
index a866f37..e2e55fd 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -153,7 +153,12 @@
                     isAbortOnError = false
                     // Avoid printing every single lint error to the terminal
                     textReport = false
-                    lintBaseline.delete()
+                    val lintDebugTask = tasks.named("lintDebug")
+                    lintDebugTask.configure {
+                        it.doFirst {
+                            lintBaseline.delete()
+                        }
+                    }
                     System.setProperty(LINT_BASELINE_CONTINUE, "true")
                 }
                 baseline(lintBaseline)
diff --git a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
index 5fed039..65197d9 100644
--- a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
@@ -41,20 +41,20 @@
     prebuilts(LibraryGroups.AUTOFILL, "1.1.0-alpha01")
     ignore(LibraryGroups.BENCHMARK.group, "benchmark-gradle-plugin")
     prebuilts(LibraryGroups.BENCHMARK, "1.1.0-alpha01")
-    prebuilts(LibraryGroups.BIOMETRIC, "biometric", "1.0.1")
-    prebuilts(LibraryGroups.BROWSER, "1.3.0-alpha03")
+    prebuilts(LibraryGroups.BIOMETRIC, "biometric", "1.1.0-alpha01")
+    prebuilts(LibraryGroups.BROWSER, "1.3.0-alpha04")
     ignore(LibraryGroups.CAMERA.group, "camera-camera2-pipe")
     ignore(LibraryGroups.CAMERA.group, "camera-camera2-pipe-integration")
     ignore(LibraryGroups.CAMERA.group, "camera-testing")
     ignore(LibraryGroups.CAMERA.group, "camera-extensions-stub")
     ignore(LibraryGroups.CAMERA.group, "camera-testlib-extensions")
-    prebuilts(LibraryGroups.CAMERA, "camera-view", "1.0.0-alpha12")
-    prebuilts(LibraryGroups.CAMERA, "camera-extensions", "1.0.0-alpha12")
+    prebuilts(LibraryGroups.CAMERA, "camera-view", "1.0.0-alpha13")
+    prebuilts(LibraryGroups.CAMERA, "camera-extensions", "1.0.0-alpha13")
             .addStubs("camera/camera-extensions-stub/camera-extensions-stub.jar")
-    prebuilts(LibraryGroups.CAMERA, "1.0.0-beta05")
+    prebuilts(LibraryGroups.CAMERA, "1.0.0-beta06")
     prebuilts(LibraryGroups.CARDVIEW, "1.0.0")
     prebuilts(LibraryGroups.COLLECTION, "1.1.0")
-    prebuilts(LibraryGroups.CONCURRENT, "1.1.0-alpha01")
+    prebuilts(LibraryGroups.CONCURRENT, "1.1.0-beta01")
     prebuilts(LibraryGroups.CONTENTPAGER, "1.0.0")
     prebuilts(LibraryGroups.COORDINATORLAYOUT, "1.1.0")
     prebuilts(LibraryGroups.CORE, "core", "1.5.0-alpha01")
@@ -68,7 +68,7 @@
     prebuilts(LibraryGroups.DRAWERLAYOUT, "1.1.0")
     prebuilts(LibraryGroups.DYNAMICANIMATION, "dynamicanimation-ktx", "1.0.0-alpha03")
     prebuilts(LibraryGroups.DYNAMICANIMATION, "1.1.0-alpha02")
-    prebuilts(LibraryGroups.EMOJI, "1.1.0-rc01")
+    prebuilts(LibraryGroups.EMOJI, "1.1.0")
     prebuilts(LibraryGroups.ENTERPRISE, "1.0.0")
     prebuilts(LibraryGroups.EXIFINTERFACE, "1.3.0-alpha01")
     ignore(LibraryGroups.FRAGMENT.group, "fragment-lint")
@@ -87,21 +87,21 @@
     ignore(LibraryGroups.LIFECYCLE.group, "lifecycle-runtime-ktx-lint")
     prebuilts(LibraryGroups.LIFECYCLE, "lifecycle-extensions", "2.2.0") // No longer published
     ignore(LibraryGroups.LIFECYCLE.group, "lifecycle-runtime-testing")
-    prebuilts(LibraryGroups.LIFECYCLE, "2.3.0-alpha04")
+    prebuilts(LibraryGroups.LIFECYCLE, "2.3.0-alpha05")
     ignore(LibraryGroups.LOADER.group, "loader-ktx")
     prebuilts(LibraryGroups.LOADER, "1.1.0")
     prebuilts(LibraryGroups.LOCALBROADCASTMANAGER, "1.1.0-alpha01")
-    prebuilts(LibraryGroups.MEDIA, "media", "1.2.0-alpha03")
+    prebuilts(LibraryGroups.MEDIA, "media", "1.2.0-alpha04")
     ignore(LibraryGroups.MEDIA2.group, "media2-exoplayer")
-    prebuilts(LibraryGroups.MEDIA2, "media2-widget", "1.0.3")
-    prebuilts(LibraryGroups.MEDIA2, "1.0.3")
+    prebuilts(LibraryGroups.MEDIA2, "media2-widget", "1.1.0-alpha01")
+    prebuilts(LibraryGroups.MEDIA2, "1.1.0-alpha01")
     prebuilts(LibraryGroups.MEDIAROUTER, "1.2.0-alpha01")
     ignore(LibraryGroups.NAVIGATION.group, "navigation-runtime-truth")
     ignore(LibraryGroups.NAVIGATION.group, "navigation-safe-args-generator")
     ignore(LibraryGroups.NAVIGATION.group, "navigation-safe-args-gradle-plugin")
-    prebuilts(LibraryGroups.NAVIGATION, "2.3.0-rc01")
+    prebuilts(LibraryGroups.NAVIGATION, "2.3.0")
     ignore(LibraryGroups.PAGING.group, "paging-guava")
-    prebuilts(LibraryGroups.PAGING, "3.0.0-alpha01")
+    prebuilts(LibraryGroups.PAGING, "3.0.0-alpha02")
     prebuilts(LibraryGroups.PALETTE, "1.0.0")
     // 1.0.1 was created to fix reference docs.  It contains no actual source changes from 1.0.0
     prebuilts(LibraryGroups.PERCENTLAYOUT, "1.0.1")
@@ -109,7 +109,7 @@
     prebuilts(LibraryGroups.PREFERENCE, "1.1.1")
     prebuilts(LibraryGroups.PRINT, "1.0.0")
     prebuilts(LibraryGroups.RECOMMENDATION, "1.0.0")
-    prebuilts(LibraryGroups.RECYCLERVIEW, "recyclerview", "1.2.0-alpha03")
+    prebuilts(LibraryGroups.RECYCLERVIEW, "recyclerview", "1.2.0-alpha04")
     prebuilts(LibraryGroups.RECYCLERVIEW, "recyclerview-selection", "2.0.0-alpha01")
     ignore(LibraryGroups.RECYCLERVIEW.group, "recyclerview-lint")
     prebuilts(LibraryGroups.REMOTECALLBACK, "1.0.0-alpha02")
@@ -136,11 +136,11 @@
     ignore(LibraryGroups.INSPECTION_EXTENSIONS.group, "sqlite-inspection")
     prebuilts(LibraryGroups.SQLITE, "2.1.0")
     prebuilts(LibraryGroups.STARTUP, "1.0.0-alpha01")
-    prebuilts(LibraryGroups.SWIPEREFRESHLAYOUT, "1.1.0-rc01")
+    prebuilts(LibraryGroups.SWIPEREFRESHLAYOUT, "1.1.0")
     prebuilts(LibraryGroups.TEXTCLASSIFIER, "1.0.0-alpha03")
-    prebuilts(LibraryGroups.TRACING, "1.0.0-alpha01")
+    prebuilts(LibraryGroups.TRACING, "1.0.0-beta01")
     ignore(LibraryGroups.TRANSITION.group, "transition-ktx")
-    prebuilts(LibraryGroups.TRANSITION, "1.3.1")
+    prebuilts(LibraryGroups.TRANSITION, "1.4.0-alpha01")
     prebuilts(LibraryGroups.TVPROVIDER, "1.0.0")
     prebuilts(LibraryGroups.VECTORDRAWABLE, "vectordrawable", "1.2.0-alpha01")
     prebuilts(LibraryGroups.VECTORDRAWABLE, "vectordrawable-animated", "1.1.0")
@@ -149,18 +149,18 @@
     prebuilts(LibraryGroups.VERSIONEDPARCELABLE, "versionedparcelable", "1.1.1")
     prebuilts(LibraryGroups.VIEWPAGER, "1.0.0")
     prebuilts(LibraryGroups.VIEWPAGER2, "1.1.0-alpha01")
-    prebuilts(LibraryGroups.WEAR, "wear", "1.1.0-rc01")
+    prebuilts(LibraryGroups.WEAR, "wear", "1.1.0-rc02")
             .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-beta01")
+    prebuilts(LibraryGroups.WEBKIT, "1.3.0-rc01")
     ignore(LibraryGroups.WINDOW.group, "window-sidecar")
     prebuilts(LibraryGroups.WINDOW, "1.0.0-alpha01")
             .addStubs("window/stubs/window-sidecar-release-0.1.0-alpha01.aar")
     ignore(LibraryGroups.WORK.group, "work-gcm")
     ignore(LibraryGroups.WORK.group, "work-runtime-lint")
     ignore(LibraryGroups.WORK.group, "work-rxjava3")
-    prebuilts(LibraryGroups.WORK, "2.4.0-beta01")
+    prebuilts(LibraryGroups.WORK, "2.4.0-rc01")
     default(Ignore)
 }
 
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index f6389489..b01ec27 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -59,7 +59,7 @@
 const val HILT_ANDROID_TESTING = "com.google.dagger:hilt-android-testing:2.28-alpha"
 const val HILT_ANDROID_GRADLE_PLUGIN = "com.google.dagger:hilt-android-gradle-plugin:2.28-alpha"
 const val INTELLIJ_ANNOTATIONS = "com.intellij:annotations:12.0"
-const val JAVAPOET = "com.squareup:javapoet:1.12.1"
+const val JAVAPOET = "com.squareup:javapoet:1.13.0"
 const val JSR250 = "javax.annotation:javax.annotation-api:1.2"
 const val JUNIT = "junit:junit:4.12"
 const val KOTLINPOET = "com.squareup:kotlinpoet:1.4.0"
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
index b844f81..bcebce8 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
@@ -21,7 +21,6 @@
 import org.gradle.api.provider.Property
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.OutputFiles
 import org.gradle.api.tasks.TaskAction
 import org.gradle.workers.WorkerExecutor
 import java.io.File
@@ -61,12 +60,6 @@
         )
     }
 
-    // Declaring outputs prevents Gradle from rerunning this task if the inputs haven't changed
-    @OutputFiles
-    fun getTaskOutputs(): List<File> {
-        return listOf(referenceApi.get().publicApiFile)
-    }
-
     @TaskAction
     fun exec() {
         check(bootClasspath.isNotEmpty()) { "Android boot classpath not set." }
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index a1bc83d..a022a62 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -64,6 +64,11 @@
         val metalavaJar = getParameters().getMetalavaClasspath().get()
 
         execOperations.javaexec {
+            // Intellij core reflects into java.util.ResourceBundle
+            it.jvmArgs = listOf(
+                "--add-opens",
+                "java.base/java.util=ALL-UNNAMED"
+            )
             it.classpath(metalavaJar)
             it.main = "com.android.tools.metalava.Driver"
             it.args = allArgs
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
index 8fd9dc6..4a965b2 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
@@ -158,6 +158,7 @@
                 task.api.set(builtApiLocation)
                 task.dependencyClasspath = javaCompileInputs.dependencyClasspath
                 task.bootClasspath = javaCompileInputs.bootClasspath
+                task.cacheEvenIfNoOutputs()
                 task.dependsOn(generateApi)
             }
 
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 e5dd64f..c5b769b 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
@@ -38,7 +38,8 @@
 
     data class Config(
         val camera: CameraId,
-        val streams: List<StreamConfig>
+        val streams: List<StreamConfig>,
+        val defaultTemplate: Int
     )
 
     /**
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt
index 94efcef..1776548 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt
@@ -20,6 +20,7 @@
 import android.hardware.camera2.CaptureRequest
 import android.hardware.camera2.CaptureResult
 import android.hardware.camera2.params.StreamConfigurationMap
+import android.view.Surface
 import androidx.camera.camera2.pipe.impl.Debug
 import java.util.concurrent.ConcurrentHashMap
 
@@ -33,7 +34,6 @@
  */
 interface Metadata {
     operator fun <T> get(key: Key<T>): T?
-    fun <T> getChecked(key: Key<T>): T
     fun <T> getOrDefault(key: Key<T>, default: T): T
 
     /**
@@ -69,7 +69,6 @@
  */
 interface CameraMetadata : Metadata, UnsafeWrapper<CameraCharacteristics> {
     operator fun <T> get(key: CameraCharacteristics.Key<T>): T?
-    fun <T> getChecked(key: CameraCharacteristics.Key<T>): T
     fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T
 
     val camera: CameraId
@@ -86,12 +85,35 @@
 }
 
 /**
- * RequestMetadata is a wrapper around [CaptureRequest].
+ * RequestMetadata wraps together all of the information about specific CaptureRequest that was
+ * submitted to Camera2.
+ *
+ * <p> This class is distinct from [Request] which is used to configure and issue a request to the
+ * [CameraGraph]. This class will report the actual keys / values that were sent to camera2 (if
+ * different) from the request that was used to create the Camera2 [CaptureRequest].
  */
 interface RequestMetadata : Metadata, UnsafeWrapper<CaptureRequest> {
     operator fun <T> get(key: CaptureRequest.Key<T>): T?
-    fun <T> getChecked(key: CaptureRequest.Key<T>): T
     fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T
+
+    /** The actual Camera2 template that was used when creating this [CaptureRequest] */
+    val template: RequestTemplate
+
+    /**
+     * A Map of Surface(s) that were submitted with this CaptureRequest and the StreamId they
+     * were associated with for this request. It's possible that not all streams specified in the
+     * request object are present in this map.
+     */
+    val streams: Map<Surface, StreamId>
+
+    /** The request object that was used to create this [CaptureRequest] */
+    val request: Request
+
+    /** An internal number used to identify a specific [CaptureRequest] */
+    val requestNumber: RequestNumber
+
+    /** The android "sequence id" that is generated by camera2 when submitting [CaptureRequest]'s */
+    val sequenceNumber: SequenceNumber
 }
 
 /**
@@ -99,9 +121,51 @@
  */
 interface ResultMetadata : Metadata, UnsafeWrapper<CaptureResult> {
     operator fun <T> get(key: CaptureResult.Key<T>): T?
-    fun <T> getChecked(key: CaptureResult.Key<T>): T
     fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T
 
     val camera: CameraId
-    val request: RequestMetadata
+    val requestMetadata: RequestMetadata
 }
+
+/**
+ * A [RequestTemplate] indicates which preset set list of parameters will be applied to a request by
+ * default. These values are defined by camera2.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class RequestTemplate(val value: Int)
+
+/**
+ * A [SequenceNumber] is the identifier that is returned when a single or repeating capture request
+ * is submitted to the camera and represents that "sequence" of captures.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class SequenceNumber(val value: Int)
+
+/**
+ * A [RequestNumber] is an artificial identifier that is created for each request that is submitted
+ * to the Camera.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class RequestNumber(val value: Long)
+
+/**
+ * A [FrameNumber] is the identifier that represents a specific exposure by the Camera. FrameNumbers
+ * increase within a specific CameraCaptureSession, and are not created until the HAL begins
+ * processing a request.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class FrameNumber(val value: Long)
+
+/**
+ * This is a timestamp from the Camera, and corresponds to the nanosecond exposure time of a Frame.
+ * While the value is expressed in nano-seconds, the precision may be much lower. In addition, the
+ * time-base of the Camera is undefined, although it's common for it to be in either Monotonic or
+ * Realtime.
+ *
+ * <p> Timestamp may differ from timestamps that are obtained from other parts of the Camera and
+ * media systems within the same device. For example, it's common for high frequency sensors to
+ * operate based on a real-time clock, while audio/visual systems commonly operate based on a
+ * monotonic clock.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class CameraTimestamp(val value: Long)
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
index 60e4c85..8e24eda 100644
--- 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
@@ -16,10 +16,201 @@
 
 package androidx.camera.camera2.pipe
 
+import android.hardware.camera2.CaptureFailure
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.CaptureResult
+import android.hardware.camera2.TotalCaptureResult
+import android.view.Surface
+
 /**
  * An immutable package of settings and outputs needed to capture a single image from the camera
- * device.
+ * device. The exact set of keys and surfaces used in the CaptureRequest builder may be different
+ * from what is specified in a request depending on how the request was submitted and on the
+ * state of the camera.
  */
-interface Request : RequestMetadata {
-    val streamIds: List<StreamId>
-}
\ No newline at end of file
+data class Request(
+    val streams: List<StreamId>,
+    val requestParameters: Map<CaptureRequest.Key<*>, Any> = emptyMap(),
+    val extraRequestParameters: Map<Metadata.Key<*>, Any> = emptyMap(),
+    val listeners: List<Listener> = emptyList(),
+    val template: Int? = null
+) {
+
+    /**
+     * This listener is used to observe the state and progress of requests that are submitted to the
+     * [CameraGraph] and can be attached to individual requests.
+     */
+    interface Listener {
+        /**
+         * This event indicates that the camera sensor has started exposing the frame associated
+         * with this Request. The timestamp will either be the beginning or end of the sensors
+         * exposure time depending on the device, and may be in a different timebase from the
+         * timestamps that are returned from the underlying buffers.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureStarted
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         * @param frameNumber the android frame number for this exposure
+         * @param timestamp the android timestamp in nanos for this exposure
+         */
+        fun onStarted(
+            requestMetadata: RequestMetadata,
+            frameNumber: FrameNumber,
+            timestamp: CameraTimestamp
+        ) {
+        }
+
+        /**
+         * This event indicates that the camera sensor has additional information about the frame
+         * associated with this Request. This method may be invoked 0 or more times before the frame
+         * receives onComplete.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureStarted
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         * @param frameNumber the android frame number for this exposure
+         * @param captureResult the current android capture result for this exposure
+         */
+        fun onProgressed(
+            requestMetadata: RequestMetadata,
+            frameNumber: FrameNumber,
+            captureResult: CaptureResult
+        ) {
+        }
+
+        /**
+         * This event indicates that all of the metadata associated with this frame has been
+         * produced. If [onProgressed] was invoked, the values returned in totalCaptureResult be the
+         * same as the values in the prior captureResult(s) for the same frame.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureStarted
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         * @param frameNumber the android frame number for this exposure
+         * @param totalCaptureResult the final android capture result for this exposure
+         */
+        fun onCompleted(
+            requestMetadata: RequestMetadata,
+            frameNumber: FrameNumber,
+            totalCaptureResult: TotalCaptureResult
+        ) {
+        }
+
+        /**
+         * onFailed occurs when a CaptureRequest failed in some way and the frame will not receive
+         * the [onCompleted] callback.
+         *
+         * Surfaces may not received images if "wasImagesCaptured" is set to false.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureFailed
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         * @param frameNumber the android frame number for this exposure
+         * @param captureFailure the android [CaptureFailure] data
+         */
+        fun onFailed(
+            requestMetadata: RequestMetadata,
+            frameNumber: FrameNumber,
+            captureFailure: CaptureFailure
+        ) {
+        }
+
+        /**
+         * onBufferLost occurs when a CaptureRequest failed to create an image for a given output
+         * stream. This method may be invoked multiple times per frame if multiple buffers were
+         * lost. This method may not be invoked when an image is lost in some situations.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureBufferLost
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         * @param frameNumber the android frame number for this exposure
+         * @param stream the internal stream that will not receive a buffer for this frame.
+         */
+        fun onBufferLost(
+            requestMetadata: RequestMetadata,
+            frameNumber: FrameNumber,
+            stream: StreamId
+        ) {
+        }
+
+        /**
+         * This is an artificial callback that will be invoked if a specific request was pending or
+         * had already been submitted to when an abort was requested. The behavior of the request is
+         * undefined if this method is invoked and images or metadata may or may not be produced
+         * for this request. Repeating requests will not receive onAborted.
+         *
+         * @param request the request object
+         */
+        fun onAborted(request: Request) {
+        }
+
+        /**
+         * Invoked after the CaptureRequest(s) have been created, but before the request is
+         * submitted to the camera. This method may be invoked multiple times if the request fails
+         * to submit or if this is a repeating request.
+         *
+         * @param request the request object that was used to create the CaptureRequest
+         * @param requestNumber the internal requestNumber for this request.
+         * @param captureRequest the android CaptureRequest object that was submitted
+         * @param streams the actual Surface objects that were used in this request.
+         */
+        fun onRequestSequenceCreated(
+            request: Request,
+            requestNumber: RequestNumber,
+            captureRequest: CaptureRequest,
+            streams: Map<StreamId, Surface>
+        ) {
+        }
+
+        /**
+         * Invoked after the CaptureRequest(s) has been submitted. This method may be invoked
+         * multiple times if the request was submitted as a repeating request.
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         */
+        fun onRequestSequenceSubmitted(requestMetadata: RequestMetadata) {
+        }
+
+        /**
+         * Invoked by Camera2 if the request was aborted after having been submitted. This method
+         * is distinct from onAborted, which is directly invoked when aborting captures.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureSequenceAborted
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         */
+        fun onRequestSequenceAborted(requestMetadata: RequestMetadata) {
+        }
+
+        /**
+         * Invoked by Camera2 if the request was completed after having been submitted. This method
+         * is distinct from onCompleted which is invoked for each frame when used with a repeating
+         * request.
+         *
+         * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureSequenceCompleted
+         *
+         * @param requestMetadata the data about the camera2 request that was sent to the camera.
+         * @param frameNumber the final frame number of this sequence.
+         */
+        fun onRequestSequenceCompleted(
+            requestMetadata: RequestMetadata,
+            frameNumber: FrameNumber
+        ) {
+        }
+    }
+}
+
+@Suppress("UNCHECKED_CAST")
+private fun <T> Request.getUnchecked(key: Metadata.Key<T>): T? =
+    this.extraRequestParameters[key] as T?
+
+operator fun <T> Request.get(key: Metadata.Key<T>): T? = getUnchecked(key)
+fun <T> Request.getOrDefault(key: Metadata.Key<T>, default: T): T = getUnchecked(key) ?: default
+
+@Suppress("UNCHECKED_CAST")
+private fun <T> Request.getUnchecked(key: CaptureRequest.Key<T>): T? =
+    this.requestParameters[key] as T?
+
+operator fun <T> Request.get(key: CaptureRequest.Key<T>): T? = getUnchecked(key)
+fun <T> Request.getOrDefault(key: CaptureRequest.Key<T>, default: T): T =
+    getUnchecked(key) ?: default
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt
index 1fa50b6..b80f564 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt
@@ -24,4 +24,4 @@
  */
 interface UnsafeWrapper<T> {
     fun unwrap(): T?
-}
\ No newline at end of file
+}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt
index 3e761b96..48c8bba 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt
@@ -41,14 +41,10 @@
     override fun <T> get(key: Metadata.Key<T>): T? = metadata[key] as T?
 
     @Suppress("UNCHECKED_CAST")
-    override fun <T> getChecked(key: Metadata.Key<T>): T = (metadata[key] as T)!!
-
-    @Suppress("UNCHECKED_CAST")
     override fun <T> getOrDefault(key: Metadata.Key<T>, default: T): T =
         metadata[key] as T? ?: default
 
     override fun <T> get(key: CameraCharacteristics.Key<T>): T? = characteristics[key]
-    override fun <T> getChecked(key: CameraCharacteristics.Key<T>): T = characteristics[key]!!
     override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T =
         characteristics[key] ?: default
 
@@ -138,6 +134,6 @@
 
     private val _streamMap: Lazy<StreamConfigurationMap> =
         lazy(LazyThreadSafetyMode.PUBLICATION) {
-            getChecked(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
+            get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
         }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt
index c7292b4..b70cb75 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt
@@ -45,7 +45,11 @@
         val context = ApplicationProvider.getApplicationContext() as Context
         val cameraPipe = CameraPipe(CameraPipe.Config(context))
         val cameraGraph = cameraPipe.create(
-            CameraGraph.Config(CameraId("0"), listOf())
+            CameraGraph.Config(
+                camera = CameraId("0"),
+                streams = listOf(),
+                defaultTemplate = 0
+            )
         )
         assertThat(cameraGraph).isNotNull()
     }
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt
index 6a9088e..0e5a7d7 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt
@@ -27,7 +27,6 @@
 import androidx.camera.camera2.pipe.testing.FakeResultMetadata
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -38,20 +37,15 @@
 class MetadataTest {
     @Test
     fun testMetadataCanRetrieveValues() {
-        val metadata = FakeMetadata(mapOf(Pair(FakeMetadata.TEST_KEY, 42)))
+        val metadata = FakeMetadata(mapOf(FakeMetadata.TEST_KEY to 42))
 
         assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
         assertThat(metadata[FakeMetadata.TEST_KEY_ABSENT]).isNull()
 
-        assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY, 84)).isEqualTo(42)
-        assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY_ABSENT, 84)).isEqualTo(84)
-
-        try {
-            assertThat(metadata.getChecked(FakeMetadata.TEST_KEY_ABSENT))
-            fail("Getting an absent key with getChecked should throw.")
-        } catch (e: Exception) {
-            // Expected
-        }
+        assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY, 84))
+            .isEqualTo(42)
+        assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY_ABSENT, 84))
+            .isEqualTo(84)
     }
 }
 
@@ -63,8 +57,8 @@
     @Test
     fun canRetrieveCameraCharacteristicsOrCameraMetadataViaInterface() {
         val metadata = FakeCameraMetadata(
-            mapOf(Pair(CameraCharacteristics.LENS_FACING, CameraCharacteristics.LENS_FACING_FRONT)),
-            mapOf(Pair(FakeMetadata.TEST_KEY, 42))
+            mapOf(CameraCharacteristics.LENS_FACING to CameraCharacteristics.LENS_FACING_FRONT),
+            mapOf(FakeMetadata.TEST_KEY to 42)
         )
 
         assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
@@ -82,16 +76,24 @@
 
     @Test
     fun canRetrieveCaptureRequestOrCameraMetadataViaInterface() {
-        val metadata = FakeRequestMetadata(
-            mapOf(Pair(CaptureRequest.JPEG_QUALITY, 95)),
-            mapOf(Pair(FakeMetadata.TEST_KEY, 42))
+        val requestMetadata = FakeRequestMetadata(
+            requestParameters = mapOf(CaptureRequest.JPEG_QUALITY to 95),
+            request = Request(
+                streams = listOf(),
+                requestParameters = mapOf(CaptureRequest.JPEG_QUALITY to 20),
+                extraRequestParameters = mapOf(FakeMetadata.TEST_KEY to 42)
+            )
         )
 
-        assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
-        assertThat(metadata[FakeMetadata.TEST_KEY_ABSENT]).isNull()
+        assertThat(requestMetadata[CaptureRequest.JPEG_QUALITY]).isEqualTo(95)
+        assertThat(requestMetadata[CaptureRequest.COLOR_CORRECTION_MODE]).isNull()
+        assertThat(requestMetadata[FakeMetadata.TEST_KEY]).isEqualTo(42)
+        assertThat(requestMetadata[FakeMetadata.TEST_KEY_ABSENT]).isNull()
 
-        assertThat(metadata[CaptureRequest.JPEG_QUALITY]).isNotNull()
-        assertThat(metadata[CaptureRequest.COLOR_CORRECTION_MODE]).isNull()
+        assertThat(requestMetadata.request[CaptureRequest.JPEG_QUALITY]).isEqualTo(20)
+        assertThat(requestMetadata.request[CaptureRequest.COLOR_CORRECTION_MODE]).isNull()
+        assertThat(requestMetadata.request[FakeMetadata.TEST_KEY]).isEqualTo(42)
+        assertThat(requestMetadata.request[FakeMetadata.TEST_KEY_ABSENT]).isNull()
     }
 }
 
@@ -103,9 +105,8 @@
     @Test
     fun canRetrieveCaptureRequestOrCameraMetadataViaInterface() {
         val metadata = FakeResultMetadata(
-            FakeRequestMetadata(),
-            result = mapOf(Pair(CaptureResult.JPEG_QUALITY, 95)),
-            metadata = mapOf(Pair(FakeMetadata.TEST_KEY, 42))
+            resultMetadata = mapOf(CaptureResult.JPEG_QUALITY to 95),
+            extraResultMetadata = mapOf(FakeMetadata.TEST_KEY to 42)
         )
 
         assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/RequestTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/RequestTest.kt
new file mode 100644
index 0000000..8f45dd5
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/RequestTest.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.camera.camera2.pipe
+
+import android.hardware.camera2.CaptureRequest
+import android.os.Build
+import androidx.camera.camera2.pipe.testing.CameraPipeRobolectricTestRunner
+import androidx.camera.camera2.pipe.testing.FakeMetadata
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+
+@SmallTest
+@RunWith(CameraPipeRobolectricTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class RequestTest {
+
+    @Test
+    fun requestHasDefaults() {
+        val request = Request(listOf(StreamId(1)))
+
+        assertThat(request.requestParameters).isEmpty()
+        assertThat(request.extraRequestParameters).isEmpty()
+        assertThat(request.template).isNull()
+        assertThat(request.listeners).isEmpty()
+
+        assertThat(request.streams).contains(StreamId(1))
+    }
+
+    @Test
+    fun canReadCaptureParameters() {
+        val request = Request(
+            listOf(StreamId(1)),
+            requestParameters = mapOf(
+                CaptureRequest.EDGE_MODE to CaptureRequest.EDGE_MODE_HIGH_QUALITY
+            ),
+            extraRequestParameters = mapOf(FakeMetadata.TEST_KEY to 42)
+        )
+
+        // Check with a valid test key
+        assertThat(request[FakeMetadata.TEST_KEY]).isEqualTo(42)
+        assertThat(request.getOrDefault(FakeMetadata.TEST_KEY, default = 24)).isEqualTo(42)
+
+        // Check with an invalid test key
+        assertThat(request[FakeMetadata.TEST_KEY_ABSENT]).isNull()
+        assertThat(request.getOrDefault(FakeMetadata.TEST_KEY_ABSENT, default = 24)).isEqualTo(24)
+
+        // Check with a valid test key
+        assertThat(request.get(CaptureRequest.EDGE_MODE))
+            .isEqualTo(CaptureRequest.EDGE_MODE_HIGH_QUALITY)
+        assertThat(request.getOrDefault(CaptureRequest.EDGE_MODE, default = 24))
+            .isEqualTo(CaptureRequest.EDGE_MODE_HIGH_QUALITY)
+
+        // Check with an invalid test key
+        assertThat(request.get(CaptureRequest.CONTROL_AE_MODE)).isNull()
+        assertThat(
+            request.getOrDefault(
+                CaptureRequest.CONTROL_AE_MODE, default = CaptureRequest.CONTROL_AE_MODE_ON
+            )
+        ).isEqualTo(CaptureRequest.CONTROL_AE_MODE_ON)
+    }
+}
\ 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 35a2da1..dccb316 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
@@ -40,7 +40,11 @@
 
     @Before
     fun setUp() {
-        val config = CameraGraph.Config(CameraId("0"), listOf())
+        val config = CameraGraph.Config(
+            camera = CameraId("0"),
+            streams = listOf(),
+            defaultTemplate = 0
+        )
         val context = ApplicationProvider.getApplicationContext() as Context
         impl = CameraGraphImpl(context, config)
     }
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt
index c024c71..0b955fe 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt
@@ -54,7 +54,11 @@
             .build()
 
         val cameraId = CameraId("0")
-        val config = CameraGraph.Config(cameraId, listOf())
+        val config = CameraGraph.Config(
+            camera = cameraId,
+            streams = listOf(),
+            defaultTemplate = 0
+        )
         val module = CameraGraphModule(config)
         val builder = component.cameraGraphComponentBuilder()
         builder.cameraGraphModule(module)
@@ -70,7 +74,15 @@
             .build()
 
         val graphComponent = component.cameraGraphComponentBuilder()
-            .cameraGraphModule(CameraGraphModule(CameraGraph.Config(CameraId("0"), listOf())))
+            .cameraGraphModule(
+                CameraGraphModule(
+                    CameraGraph.Config(
+                        camera = CameraId("0"),
+                        streams = listOf(),
+                        defaultTemplate = 0
+                    )
+                )
+            )
             .build()
 
         val graph = graphComponent.cameraGraph()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt
index f88d2c9..ce66bc1 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt
@@ -22,11 +22,17 @@
 import android.hardware.camera2.CaptureRequest
 import android.hardware.camera2.CaptureResult
 import android.hardware.camera2.params.StreamConfigurationMap
+import android.view.Surface
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraMetadata
 import androidx.camera.camera2.pipe.Metadata
+import androidx.camera.camera2.pipe.Request
 import androidx.camera.camera2.pipe.RequestMetadata
+import androidx.camera.camera2.pipe.RequestNumber
+import androidx.camera.camera2.pipe.RequestTemplate
 import androidx.camera.camera2.pipe.ResultMetadata
+import androidx.camera.camera2.pipe.SequenceNumber
+import androidx.camera.camera2.pipe.StreamId
 
 /**
  * Utility class for interacting with objects that require pre-populated Metadata.
@@ -44,8 +50,6 @@
         val value = values[key]
         return if (value == null) default else value as T
     }
-
-    override fun <T> getChecked(key: Metadata.Key<T>): T = (values[key] as T)!!
 }
 
 /**
@@ -59,12 +63,9 @@
     private val values = characteristics.toMap()
 
     override fun <T> get(key: CameraCharacteristics.Key<T>): T? = values[key] as T?
-    override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T {
-        val value = values[key]
-        return if (value == null) default else value as T
-    }
+    override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T =
+        get(key) ?: default
 
-    override fun <T> getChecked(key: CameraCharacteristics.Key<T>): T = (values[key] as T)!!
     override val camera = CameraId("Fake")
     override val isRedacted = false
     override val keys: Set<CameraCharacteristics.Key<*>> = emptySet()
@@ -78,7 +79,8 @@
 
     override fun unwrap(): CameraCharacteristics? {
         throw UnsupportedOperationException(
-            "FakeCameraMetadata does not wrap CameraCharacteristics")
+            "FakeCameraMetadata does not wrap CameraCharacteristics"
+        )
     }
 }
 
@@ -86,21 +88,22 @@
  * Utility class for interacting with objects require specific [CaptureRequest] metadata
  */
 class FakeRequestMetadata(
-    request: Map<CaptureRequest.Key<*>, Any?> = emptyMap(),
-    metadata: Map<Metadata.Key<*>, Any?> = emptyMap()
-) : FakeMetadata(metadata), RequestMetadata {
-    private val values = request.toMap()
+    private val requestParameters: Map<CaptureRequest.Key<*>, Any?> = emptyMap(),
+    extraRequestParameters: Map<Metadata.Key<*>, Any?> = emptyMap(),
+    override val template: RequestTemplate = RequestTemplate(0),
+    override val streams: Map<Surface, StreamId> = mapOf(),
+    override val request: Request = Request(listOf()),
+    override val requestNumber: RequestNumber = RequestNumber(4321),
+    override val sequenceNumber: SequenceNumber = SequenceNumber(1234)
+) : FakeMetadata(request.extraRequestParameters.plus(extraRequestParameters)), RequestMetadata {
 
-    override fun <T> get(key: CaptureRequest.Key<T>): T? = values[key] as T?
-    override fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T {
-        val value = values[key]
-        return if (value == null) default else value as T
-    }
+    override fun <T> get(key: CaptureRequest.Key<T>): T? = requestParameters[key] as T?
+    override fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T = get(key) ?: default
 
-    override fun <T> getChecked(key: CaptureRequest.Key<T>): T = (values[key] as T)!!
     override fun unwrap(): CaptureRequest? {
         throw UnsupportedOperationException(
-            "FakeCameraMetadata does not wrap CameraCharacteristics")
+            "FakeCameraMetadata does not wrap a real CaptureRequest"
+        )
     }
 }
 
@@ -108,24 +111,18 @@
  * Utility class for interacting with objects require specific [CaptureResult] metadata
  */
 class FakeResultMetadata(
-    override val request: RequestMetadata,
-    override val camera: CameraId = CameraId("Fake"),
-    result: Map<CaptureResult.Key<*>, Any?> = emptyMap(),
-    metadata: Map<Metadata.Key<*>, Any?> = emptyMap()
-) : FakeMetadata(metadata), ResultMetadata {
+    private val resultMetadata: Map<CaptureResult.Key<*>, Any?> = emptyMap(),
+    extraResultMetadata: Map<Metadata.Key<*>, Any?> = emptyMap(),
+    override val requestMetadata: RequestMetadata = FakeRequestMetadata(),
+    override val camera: CameraId = CameraId("Fake")
+) : FakeMetadata(extraResultMetadata), ResultMetadata {
 
-    private val values = result.toMap()
-
-    override fun <T> get(key: CaptureResult.Key<T>): T? = values[key] as T?
-    override fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T {
-        val value = values[key]
-        return if (value == null) default else value as T
-    }
-
-    override fun <T> getChecked(key: CaptureResult.Key<T>): T = (values[key] as T)!!
+    override fun <T> get(key: CaptureResult.Key<T>): T? = resultMetadata[key] as T?
+    override fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T = get(key) ?: default
 
     override fun unwrap(): CaptureResult? {
         throw UnsupportedOperationException(
-            "FakeCameraMetadata does not wrap CameraCharacteristics")
+            "FakeCameraMetadata does not wrap a real CaptureResult"
+        )
     }
 }
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
index e94f1c2..bd55d88 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
@@ -20,7 +20,6 @@
 import static androidx.camera.testing.CoreAppTestUtil.clearDeviceUI;
 
 import static org.junit.Assume.assumeNotNull;
-import static org.junit.Assume.assumeTrue;
 
 import android.app.Instrumentation;
 import android.content.Context;
@@ -41,12 +40,13 @@
 import androidx.test.filters.SdkSuppress;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
-import androidx.test.rule.GrantPermissionRule;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import java.util.concurrent.ExecutionException;
@@ -55,9 +55,9 @@
 @LargeTest
 public class CameraDisconnectTest {
 
-    @Rule
-    public GrantPermissionRule mCameraPermissionRule =
-            GrantPermissionRule.grant(android.Manifest.permission.CAMERA);
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+
     @Rule
     public ActivityTestRule<CameraXTestActivity> mCameraXTestActivityRule =
             new ActivityTestRule<>(CameraXTestActivity.class, true, false);
@@ -70,7 +70,6 @@
 
     @Before
     public void setUp() {
-        assumeTrue(CameraUtil.deviceHasCamera());
         CoreAppTestUtil.assumeCompatibleDevice();
 
         Context context = ApplicationProvider.getApplicationContext();
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
index 947d8c1..4324c31 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
@@ -20,7 +20,6 @@
 
 import static org.junit.Assume.assumeTrue;
 
-import android.Manifest;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.os.Handler;
@@ -48,12 +47,12 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import java.util.HashSet;
@@ -78,13 +77,11 @@
     private CameraSelector mCameraSelector;
     private FakeLifecycleOwner mLifecycleOwner;
 
-    @Rule
-    public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA);
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
 
     @Before
     public void setUp() {
-        assumeTrue(CameraUtil.deviceHasCamera());
         synchronized (mAnalysisResultLock) {
             mAnalysisResults = new HashSet<>();
         }
@@ -125,49 +122,83 @@
     }
 
     @Test
-    public void canSupportGuaranteedSize()
+    public void canSupportGuaranteedSizeFront()
             throws InterruptedException, CameraInfoUnavailableException {
         // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
         // Using for-loop to check both front and back device cameras can support the guaranteed
         // 640x480 size.
-        for (int i = 0; i <= 1; i++) {
-            final int lensFacing = i;
-            if (!CameraUtil.hasCameraWithLensFacing(lensFacing)) {
-                continue;
-            }
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
 
-            // Checks camera device sensor degrees to set correct target rotation value to make sure
-            // the exactly matching result size 640x480 can be selected if the device supports it.
-            Integer sensorOrientation = CameraUtil.getSensorOrientation(
-                    CameraSelector.LENS_FACING_BACK);
-            boolean isRotateNeeded = (sensorOrientation % 180) != 0;
-            ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
-                    GUARANTEED_RESOLUTION).setTargetRotation(
-                    isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
-            mInstrumentation.runOnMainSync(() -> {
-                CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
-                        lensFacing).build();
-                CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase);
-                mLifecycleOwner.startAndResume();
-                useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
-            });
+        // Checks camera device sensor degrees to set correct target rotation value to make sure
+        // the exactly matching result size 640x480 can be selected if the device supports it.
+        Integer sensorOrientation = CameraUtil.getSensorOrientation(
+                CameraSelector.LENS_FACING_FRONT);
+        boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+        ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
+                GUARANTEED_RESOLUTION).setTargetRotation(
+                isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+        mInstrumentation.runOnMainSync(() -> {
+            CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_FRONT).build();
+            CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase);
+            mLifecycleOwner.startAndResume();
+            useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
+        });
+        assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
 
-            assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
-
-            synchronized (mAnalysisResultLock) {
-                // Check the analyzed image exactly matches 640x480 size. This test can also check
-                // whether the guaranteed resolution 640x480 is really supported for YUV_420_888
-                // format on the devices when running the test.
-                assertThat(GUARANTEED_RESOLUTION).isEqualTo(
-                        mAnalysisResults.iterator().next().mResolution);
-            }
-
-            // Reset the environment to run test for the other lens facing camera device.
-            mInstrumentation.runOnMainSync(() -> {
-                CameraX.unbindAll();
-                mLifecycleOwner.pauseAndStop();
-            });
+        synchronized (mAnalysisResultLock) {
+            // Check the analyzed image exactly matches 640x480 size. This test can also check
+            // whether the guaranteed resolution 640x480 is really supported for YUV_420_888
+            // format on the devices when running the test.
+            assertThat(GUARANTEED_RESOLUTION).isEqualTo(
+                    mAnalysisResults.iterator().next().mResolution);
         }
+
+        // Reset the environment to run test for the other lens facing camera device.
+        mInstrumentation.runOnMainSync(() -> {
+            CameraX.unbindAll();
+            mLifecycleOwner.pauseAndStop();
+        });
+    }
+
+    @Test
+    public void canSupportGuaranteedSizeBack()
+            throws InterruptedException, CameraInfoUnavailableException {
+        // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
+        // Using for-loop to check both front and back device cameras can support the guaranteed
+        // 640x480 size.
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
+
+        // Checks camera device sensor degrees to set correct target rotation value to make sure
+        // the exactly matching result size 640x480 can be selected if the device supports it.
+        Integer sensorOrientation = CameraUtil.getSensorOrientation(
+                CameraSelector.LENS_FACING_BACK);
+        boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+        ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
+                GUARANTEED_RESOLUTION).setTargetRotation(
+                isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+        mInstrumentation.runOnMainSync(() -> {
+            CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_BACK).build();
+            CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase);
+            mLifecycleOwner.startAndResume();
+            useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
+        });
+        assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
+
+        synchronized (mAnalysisResultLock) {
+            // Check the analyzed image exactly matches 640x480 size. This test can also check
+            // whether the guaranteed resolution 640x480 is really supported for YUV_420_888
+            // format on the devices when running the test.
+            assertThat(GUARANTEED_RESOLUTION).isEqualTo(
+                    mAnalysisResults.iterator().next().mResolution);
+        }
+
+        // Reset the environment to run test for the other lens facing camera device.
+        mInstrumentation.runOnMainSync(() -> {
+            CameraX.unbindAll();
+            mLifecycleOwner.pauseAndStop();
+        });
     }
 
     @Test
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
index f1e8d97..4c6cfdd 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
@@ -88,8 +88,10 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
@@ -113,9 +115,12 @@
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public final class ImageCaptureTest {
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+
     @Rule
     public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+            Manifest.permission.WRITE_EXTERNAL_STORAGE);
 
     private static final Size DEFAULT_RESOLUTION = new Size(640, 480);
     private static final Size GUARANTEED_RESOLUTION = new Size(640, 480);
@@ -147,8 +152,6 @@
     @Before
     @UseExperimental(markerClass = ExperimentalCamera2Interop.class)
     public void setUp() throws ExecutionException, InterruptedException {
-        assumeTrue(CameraUtil.deviceHasCamera());
-
         createDefaultPictureFolderIfNotExist();
         Context context = ApplicationProvider.getApplicationContext();
         CameraXConfig cameraXConfig = Camera2Config.defaultConfig();
@@ -161,11 +164,6 @@
         mLifecycleOwner = new FakeLifecycleOwner();
         mMainExecutor = ContextCompat.getMainExecutor(context);
         mContentResolver = ApplicationProvider.getApplicationContext().getContentResolver();
-
-        // Get the camera ID
-        mInstrumentation.runOnMainSync(() -> {
-            CameraX.bindToLifecycle(mLifecycleOwner, BACK_SELECTOR);
-        });
     }
 
     @After
@@ -213,52 +211,95 @@
     }
 
     @Test
-    public void canSupportGuaranteedSize()
+    public void canSupportGuaranteedSizeFront()
             throws CameraInfoUnavailableException, ExecutionException, InterruptedException {
         // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
         // Using for-loop to check both front and back device cameras can support the guaranteed
         // 640x480 size.
-        for (int i = 0; i <= 1; i++) {
-            final int lensFacing = i;
-            if (!CameraUtil.hasCameraWithLensFacing(lensFacing)) {
-                continue;
-            }
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
 
-            // Checks camera device sensor degrees to set correct target rotation value to make sure
-            // the exactly matching result size 640x480 can be selected if the device supports it.
-            Integer sensorOrientation = CameraUtil.getSensorOrientation(BACK_LENS_FACING);
-            boolean isRotateNeeded = (sensorOrientation % 180) != 0;
-            ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
-                    GUARANTEED_RESOLUTION).setTargetRotation(
-                    isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+        // Checks camera device sensor degrees to set correct target rotation value to make sure
+        // the exactly matching result size 640x480 can be selected if the device supports it.
+        Integer sensorOrientation = CameraUtil.getSensorOrientation(
+                CameraSelector.LENS_FACING_FRONT);
+        boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+        ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
+                GUARANTEED_RESOLUTION).setTargetRotation(
+                isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
 
-            mInstrumentation.runOnMainSync(
-                    () -> {
-                        CameraSelector cameraSelector =
-                                new CameraSelector.Builder().requireLensFacing(lensFacing).build();
-                        CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase,
-                                mRepeatingUseCase);
-                        mLifecycleOwner.startAndResume();
-                    });
+        mInstrumentation.runOnMainSync(
+                () -> {
+                    CameraSelector cameraSelector =
+                            new CameraSelector.Builder().requireLensFacing(
+                                    CameraSelector.LENS_FACING_FRONT).build();
+                    CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase,
+                            mRepeatingUseCase);
+                    mLifecycleOwner.startAndResume();
+                });
 
-            ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
-            OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
-            useCase.takePicture(mMainExecutor, callback);
-            // Wait for the signal that the image has been captured.
-            verify(callback, timeout(10000)).onCaptureSuccess(any(ImageProxy.class));
+        ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
+        OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
+        useCase.takePicture(mMainExecutor, callback);
+        // Wait for the signal that the image has been captured.
+        verify(callback, timeout(10000)).onCaptureSuccess(any(ImageProxy.class));
 
-            // Check the captured image exactly matches 640x480 size. This test can also check
-            // whether the guaranteed resolution 640x480 is really supported for JPEG format on the
-            // devices when running the test.
-            assertEquals(GUARANTEED_RESOLUTION, imageProperties.get().size);
+        // Check the captured image exactly matches 640x480 size. This test can also check
+        // whether the guaranteed resolution 640x480 is really supported for JPEG format on the
+        // devices when running the test.
+        assertEquals(GUARANTEED_RESOLUTION, imageProperties.get().size);
 
-            // Reset the environment to run test for the other lens facing camera device.
-            mInstrumentation.runOnMainSync(() -> {
-                CameraX.unbindAll();
-                mLifecycleOwner.pauseAndStop();
-                mRepeatingUseCase = new FakeRepeatingUseCase(mFakeUseCaseConfig);
-            });
-        }
+        // Reset the environment to run test for the other lens facing camera device.
+        mInstrumentation.runOnMainSync(() -> {
+            CameraX.unbindAll();
+            mLifecycleOwner.pauseAndStop();
+            mRepeatingUseCase = new FakeRepeatingUseCase(mFakeUseCaseConfig);
+        });
+    }
+
+    @Test
+    public void canSupportGuaranteedSizeBack()
+            throws CameraInfoUnavailableException, ExecutionException, InterruptedException {
+        // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
+        // Using for-loop to check both front and back device cameras can support the guaranteed
+        // 640x480 size.
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
+
+        // Checks camera device sensor degrees to set correct target rotation value to make sure
+        // the exactly matching result size 640x480 can be selected if the device supports it.
+        Integer sensorOrientation = CameraUtil.getSensorOrientation(
+                CameraSelector.LENS_FACING_BACK);
+        boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+        ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
+                GUARANTEED_RESOLUTION).setTargetRotation(
+                isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+
+        mInstrumentation.runOnMainSync(
+                () -> {
+                    CameraSelector cameraSelector =
+                            new CameraSelector.Builder().requireLensFacing(
+                                    CameraSelector.LENS_FACING_BACK).build();
+                    CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase,
+                            mRepeatingUseCase);
+                    mLifecycleOwner.startAndResume();
+                });
+
+        ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
+        OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
+        useCase.takePicture(mMainExecutor, callback);
+        // Wait for the signal that the image has been captured.
+        verify(callback, timeout(10000)).onCaptureSuccess(any(ImageProxy.class));
+
+        // Check the captured image exactly matches 640x480 size. This test can also check
+        // whether the guaranteed resolution 640x480 is really supported for JPEG format on the
+        // devices when running the test.
+        assertEquals(GUARANTEED_RESOLUTION, imageProperties.get().size);
+
+        // Reset the environment to run test for the other lens facing camera device.
+        mInstrumentation.runOnMainSync(() -> {
+            CameraX.unbindAll();
+            mLifecycleOwner.pauseAndStop();
+            mRepeatingUseCase = new FakeRepeatingUseCase(mFakeUseCaseConfig);
+        });
     }
 
     @Test
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
index 0785dc3..7f4ca7c 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
@@ -28,7 +28,6 @@
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 
-import android.Manifest;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.graphics.SurfaceTexture;
@@ -52,12 +51,12 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import java.util.concurrent.ExecutionException;
@@ -72,9 +71,8 @@
 @RunWith(AndroidJUnit4.class)
 public final class PreviewTest {
 
-    @Rule
-    public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA);
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
 
     private static final String ANY_THREAD_NAME = "any-thread-name";
     private static final Size GUARANTEED_RESOLUTION = new Size(640, 480);
@@ -89,8 +87,6 @@
 
     @Before
     public void setUp() throws ExecutionException, InterruptedException {
-        assumeTrue(CameraUtil.deviceHasCamera());
-
         final Context context = ApplicationProvider.getApplicationContext();
         CameraXConfig cameraXConfig = Camera2Config.defaultConfig();
         CameraX.initialize(context, cameraXConfig).get();
@@ -230,50 +226,84 @@
     }
 
     @Test
-    public void canSupportGuaranteedSize()
+    public void canSupportGuaranteedSizeFront()
             throws InterruptedException, CameraInfoUnavailableException {
         // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
         // Using for-loop to check both front and back device cameras can support the guaranteed
         // 640x480 size.
-        for (int i = 0; i <= 1; i++) {
-            final int lensFacing = i;
-            if (!CameraUtil.hasCameraWithLensFacing(lensFacing)) {
-                continue;
-            }
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
 
-            // Checks camera device sensor degrees to set correct target rotation value to make sure
-            // the exactly matching result size 640x480 can be selected if the device supports it.
-            Integer sensorOrientation = CameraUtil.getSensorOrientation(
-                    CameraSelector.LENS_FACING_BACK);
-            boolean isRotateNeeded = (sensorOrientation % 180) != 0;
-            Preview preview = new Preview.Builder().setTargetResolution(
-                    GUARANTEED_RESOLUTION).setTargetRotation(
-                    isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+        // Checks camera device sensor degrees to set correct target rotation value to make sure
+        // the exactly matching result size 640x480 can be selected if the device supports it.
+        Integer sensorOrientation = CameraUtil.getSensorOrientation(
+                CameraSelector.LENS_FACING_FRONT);
+        boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+        Preview preview = new Preview.Builder().setTargetResolution(
+                GUARANTEED_RESOLUTION).setTargetRotation(
+                isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
 
-            mInstrumentation.runOnMainSync(() -> {
-                preview.setSurfaceProvider(getSurfaceProvider(null));
-                CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
-                        lensFacing).build();
-                CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, preview);
-                mLifecycleOwner.startAndResume();
-            });
+        mInstrumentation.runOnMainSync(() -> {
+            preview.setSurfaceProvider(getSurfaceProvider(null));
+            CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_FRONT).build();
+            CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, preview);
+            mLifecycleOwner.startAndResume();
+        });
 
-            // Assert.
-            assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
+        // Assert.
+        assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
 
-            // Check whether 640x480 is selected for the preview use case. This test can also check
-            // whether the guaranteed resolution 640x480 is really supported for SurfaceTexture
-            // format on the devices when running the test.
-            assertEquals(GUARANTEED_RESOLUTION, mPreviewResolution);
+        // Check whether 640x480 is selected for the preview use case. This test can also check
+        // whether the guaranteed resolution 640x480 is really supported for SurfaceTexture
+        // format on the devices when running the test.
+        assertEquals(GUARANTEED_RESOLUTION, mPreviewResolution);
 
-            // Reset the environment to run test for the other lens facing camera device.
-            mInstrumentation.runOnMainSync(() -> {
-                CameraX.unbindAll();
-                mLifecycleOwner.pauseAndStop();
-            });
-        }
+        // Reset the environment to run test for the other lens facing camera device.
+        mInstrumentation.runOnMainSync(() -> {
+            CameraX.unbindAll();
+            mLifecycleOwner.pauseAndStop();
+        });
     }
 
+    @Test
+    public void canSupportGuaranteedSizeBack()
+            throws InterruptedException, CameraInfoUnavailableException {
+        // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
+        // Using for-loop to check both front and back device cameras can support the guaranteed
+        // 640x480 size.
+        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
+
+        // Checks camera device sensor degrees to set correct target rotation value to make sure
+        // the exactly matching result size 640x480 can be selected if the device supports it.
+        Integer sensorOrientation = CameraUtil.getSensorOrientation(
+                CameraSelector.LENS_FACING_BACK);
+        boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+        Preview preview = new Preview.Builder().setTargetResolution(
+                GUARANTEED_RESOLUTION).setTargetRotation(
+                isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+
+        mInstrumentation.runOnMainSync(() -> {
+            preview.setSurfaceProvider(getSurfaceProvider(null));
+            CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+                    CameraSelector.LENS_FACING_BACK).build();
+            CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, preview);
+            mLifecycleOwner.startAndResume();
+        });
+
+        // Assert.
+        assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
+
+        // Check whether 640x480 is selected for the preview use case. This test can also check
+        // whether the guaranteed resolution 640x480 is really supported for SurfaceTexture
+        // format on the devices when running the test.
+        assertEquals(GUARANTEED_RESOLUTION, mPreviewResolution);
+
+        // Reset the environment to run test for the other lens facing camera device.
+        mInstrumentation.runOnMainSync(() -> {
+            CameraX.unbindAll();
+            mLifecycleOwner.pauseAndStop();
+        });
+    }
 
     @Test
     public void setMultipleNonNullSurfaceProviders_getsFrame() throws InterruptedException {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
index 376d434..00704c1 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
@@ -20,9 +20,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assume.assumeTrue;
-
-import android.Manifest;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.graphics.SurfaceTexture;
@@ -46,12 +43,12 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import java.util.concurrent.ExecutionException;
@@ -66,17 +63,14 @@
 public final class UseCaseCombinationTest {
     private static final CameraSelector DEFAULT_SELECTOR = CameraSelector.DEFAULT_BACK_CAMERA;
     private final MutableLiveData<Long> mAnalysisResult = new MutableLiveData<>();
-    @Rule
-    public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO);
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
     private Semaphore mSemaphore;
     private FakeLifecycleOwner mLifecycle;
 
     @Before
     public void setUp() {
-        assumeTrue(CameraUtil.deviceHasCamera());
-
         final Context context = ApplicationProvider.getApplicationContext();
         final CameraXConfig config = Camera2Config.defaultConfig();
         CameraX.initialize(context, config);
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 8b6bfd4..d3daaa4 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
@@ -20,7 +20,6 @@
 
 import static junit.framework.TestCase.assertTrue;
 
-import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -29,7 +28,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.internal.verification.VerificationModeFactory.times;
 
-import android.Manifest;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraDevice;
 import android.media.ImageReader;
@@ -74,7 +72,6 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
-import androidx.test.rule.GrantPermissionRule;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -82,8 +79,9 @@
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Rule;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
@@ -119,9 +117,9 @@
     private static CameraFactory sCameraFactory;
     static ExecutorService sCameraExecutor;
 
-    @Rule
-    public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA);
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+
 
     private ArrayList<FakeUseCase> mFakeUseCases = new ArrayList<>();
     private Camera2CameraImpl mCamera2CameraImpl;
@@ -150,7 +148,6 @@
 
     @Before
     public void setup() throws CameraUnavailableException {
-        assumeTrue(CameraUtil.deviceHasCamera());
         mMockOnImageAvailableListener = Mockito.mock(ImageReader.OnImageAvailableListener.class);
         mSessionStateCallback = new SemaphoreReleasingCamera2Callbacks.SessionStateCallback();
         mCameraId = CameraUtil.getCameraIdWithLensFacing(DEFAULT_LENS_FACING);
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
index adf56c7..d5be316 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
@@ -26,7 +26,6 @@
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 
-import android.Manifest;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.hardware.camera2.CameraAccessException;
@@ -42,6 +41,7 @@
 import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks;
 import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks.DeviceStateCallback;
 import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks.SessionCaptureCallback;
+import androidx.camera.camera2.interop.Camera2CameraInfo;
 import androidx.camera.camera2.interop.Camera2Interop;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.Camera;
@@ -52,7 +52,6 @@
 import androidx.camera.core.CameraX;
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.ImageCapture;
-import androidx.camera.core.impl.CameraInternal;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.fakes.FakeLifecycleOwner;
@@ -64,12 +63,12 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import java.util.Arrays;
@@ -105,9 +104,8 @@
                 mAnalysisResult2.postValue(image.getImageInfo().getTimestamp());
                 image.close();
             };
-    @Rule
-    public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA);
+    @ClassRule
+    public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
 
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
 
@@ -125,7 +123,6 @@
 
     @Before
     public void setUp() {
-        assumeTrue(CameraUtil.deviceHasCamera());
         Context context = ApplicationProvider.getApplicationContext();
         CameraX.initialize(context, Camera2Config.defaultConfig());
         mLifecycle = new FakeLifecycleOwner();
@@ -610,7 +607,7 @@
                 useCase);
 
         List<String> camera2IdList = Arrays.asList(CameraUtil.getCameraManager().getCameraIdList());
-        assertThat(((CameraInternal) camera).getCameraInfoInternal().getCameraId()).isEqualTo(
+        assertThat(Camera2CameraInfo.extractCameraId(camera.getCameraInfo())).isEqualTo(
                 camera2IdList.iterator().next());
     }
 
@@ -624,7 +621,7 @@
                 new CameraSelector.Builder().requireLensFacing(DEFAULT_LENS_FACING).build(),
                 useCase);
 
-        assertThat(((CameraInternal) camera).getCameraInfoInternal().getCameraId()).isEqualTo(
+        assertThat(Camera2CameraInfo.extractCameraId(camera.getCameraInfo())).isEqualTo(
                 CameraUtil.getCameraIdWithLensFacing(DEFAULT_LENS_FACING));
     }
 
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
index 79a7d07..b43fdb4 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
@@ -21,7 +21,6 @@
 import static junit.framework.TestCase.assertTrue;
 import static junit.framework.TestCase.fail;
 
-import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
@@ -32,7 +31,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
-import android.Manifest;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
@@ -66,15 +64,15 @@
 import androidx.core.os.HandlerCompat;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
-import androidx.test.rule.GrantPermissionRule;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
 import org.junit.After;
 import org.junit.AssumptionViolatedException;
 import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
@@ -107,14 +105,12 @@
 
     private final List<CaptureSession> mCaptureSessions = new ArrayList<>();
 
-    @Rule
-    public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
-            Manifest.permission.CAMERA);
+    @ClassRule
+    public static TestRule sUseCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
 
     @Before
     public void setup() throws CameraAccessException, InterruptedException,
             AssumptionViolatedException, TimeoutException, ExecutionException {
-        assumeTrue(CameraUtil.deviceHasCamera());
         mTestParameters0 = new CaptureSessionTestParameters("mTestParameters0");
         mTestParameters1 = new CaptureSessionTestParameters("mTestParameters1");
         mCameraDeviceHolder = CameraUtil.getCameraDevice();
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
index 3a9dfc0..b10101c 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
@@ -56,9 +56,11 @@
 import androidx.camera.core.impl.SurfaceConfig.ConfigType;
 import androidx.camera.core.impl.UseCaseConfig;
 import androidx.camera.core.impl.VideoCaptureConfig;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.Configs;
 import androidx.camera.testing.StreamConfigurationMapUtil;
+import androidx.camera.testing.SurfaceTextureProvider;
 import androidx.camera.testing.fakes.FakeCamera;
 import androidx.camera.testing.fakes.FakeCameraFactory;
 import androidx.camera.testing.fakes.FakeLifecycleOwner;
@@ -486,6 +488,9 @@
         final Preview preview = new Preview.Builder()
                 .setTargetAspectRatio(AspectRatio.RATIO_16_9)
                 .build();
+        preview.setSurfaceProvider(CameraXExecutors.directExecutor(),
+                SurfaceTextureProvider.createSurfaceTextureProvider(mock(
+                        SurfaceTextureProvider.SurfaceTextureCallback.class)));
 
         // Ensure we are bound to a camera to ensure aspect ratio correction is applied.
         FakeLifecycleOwner fakeLifecycle = new FakeLifecycleOwner();
@@ -534,6 +539,9 @@
                 mContext, CAMERA_ID, mMockCamcorderProfileHelper);
 
         Preview preview = new Preview.Builder().build();
+        preview.setSurfaceProvider(CameraXExecutors.directExecutor(),
+                SurfaceTextureProvider.createSurfaceTextureProvider(mock(
+                        SurfaceTextureProvider.SurfaceTextureCallback.class)));
         ImageCapture imageCapture = new ImageCapture.Builder().build();
         ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
 
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
index 4c87c16e..71f0a69 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
@@ -240,10 +240,10 @@
 
     @Test
     @UiThreadTest
-    public void bind_createsNewUseCaseMediator() {
+    public void bind_createsNewLifecycleCamera() {
         initCameraX();
         CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, new FakeUseCase());
-        // One observer is the use case mediator. The other observer removes the use case upon the
+        // One observer is the LifecycleCamera. The other observer removes the use case upon the
         // lifecycle's destruction.
         assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
     }
@@ -275,7 +275,7 @@
 
     @Test
     @UiThreadTest
-    public void bind_createsDifferentUseCaseMediators_forDifferentLifecycles() {
+    public void bind_createsDifferentLifecycleCameras_forDifferentLifecycles() {
         initCameraX();
         CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR,
                 new FakeUseCaseConfig.Builder().setTargetName("config0").build());
@@ -284,7 +284,7 @@
         CameraX.bindToLifecycle(anotherLifecycle, CAMERA_SELECTOR,
                 new FakeUseCaseConfig.Builder().setTargetName("config1").build());
 
-        // One observer is the use case mediator. The other observer removes the use case upon the
+        // One observer is the LifecycleCamera. The other observer removes the use case upon the
         // lifecycle's destruction.
         assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
         assertThat(anotherLifecycle.getObserverCount()).isEqualTo(2);
@@ -373,19 +373,6 @@
     }
 
     @Test
-    @UiThreadTest
-    public void bindUseCases_canUpdateUseCase() {
-        initCameraX();
-        FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().getUseCaseConfig();
-        FakeUseCase fakeUseCase = new FakeUseCase(config0);
-
-        Camera camera = CameraX.bindToLifecycle(mLifecycle, CameraSelector.DEFAULT_BACK_CAMERA,
-                fakeUseCase);
-
-        assertThat(fakeUseCase.getCamera()).isEqualTo(camera);
-    }
-
-    @Test
     public void requestingDefaultConfiguration_returnsDefaultConfiguration() {
         initCameraX();
         // Requesting a default configuration will throw if CameraX is not initialized.
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
similarity index 98%
rename from camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisTest.java
rename to camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
index 27801a3bf..c165a4e 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
@@ -41,7 +41,8 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class ImageAnalysisTest {
+public class ImageAnalysisDeviceTest {
+
     private final CameraInternal mMockCameraInternal = mock(CameraInternal.class);
     private final ImageAnalysis.Analyzer mMockAnalyzer = mock(ImageAnalysis.Analyzer.class);
 
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
index 4cf2448..94de7cb 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
@@ -27,10 +27,13 @@
 import android.util.Size;
 
 import androidx.camera.core.impl.CaptureConfig;
+import androidx.camera.core.impl.ImageCaptureConfig;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
 import androidx.camera.testing.fakes.FakeAppConfig;
 import androidx.camera.testing.fakes.FakeCamera;
 import androidx.camera.testing.fakes.FakeCameraControl;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
@@ -42,6 +45,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
+import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 
@@ -51,7 +56,7 @@
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class ImageCaptureTest {
-    private FakeCamera mFakeCamera;
+    private CameraUseCaseAdapter mCameraUseCaseAdapter;
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
 
     @Before
@@ -62,7 +67,17 @@
         Context context = ApplicationProvider.getApplicationContext();
         CameraX.initialize(context, cameraXConfig).get();
 
-        mFakeCamera = new FakeCamera();
+        FakeCamera fakeCamera = new FakeCamera("fakeCameraId");
+
+        FakeCameraDeviceSurfaceManager fakeCameraDeviceSurfaceManager =
+                new FakeCameraDeviceSurfaceManager();
+        fakeCameraDeviceSurfaceManager.setSuggestedResolution("fakeCameraId",
+                ImageCaptureConfig.class,
+                new Size(640, 480));
+
+        mCameraUseCaseAdapter = new CameraUseCaseAdapter(fakeCamera,
+                new LinkedHashSet<>(Collections.singleton(fakeCamera)),
+                fakeCameraDeviceSurfaceManager);
     }
 
     @After
@@ -74,12 +89,17 @@
     public void onCaptureCancelled_onErrorCAMERA_CLOSED() {
         ImageCapture imageCapture = createImageCapture();
 
-        mInstrumentation.runOnMainSync(() -> bind(imageCapture));
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                mCameraUseCaseAdapter.addUseCases(Collections.singleton(imageCapture));
+            } catch (CameraUseCaseAdapter.CameraException ignore) {
+            }
+        });
 
         ImageCapture.OnImageCapturedCallback callback = mock(
                 ImageCapture.OnImageCapturedCallback.class);
         FakeCameraControl fakeCameraControl =
-                ((FakeCameraControl) mFakeCamera.getCameraControlInternal());
+                ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
 
         fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
             // Notify the cancel after the capture request has been successfully submitted
@@ -100,12 +120,17 @@
     public void onRequestFailed_OnErrorCAPTURE_FAILED() {
         ImageCapture imageCapture = createImageCapture();
 
-        mInstrumentation.runOnMainSync(() -> bind(imageCapture));
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                mCameraUseCaseAdapter.addUseCases(Collections.singleton(imageCapture));
+            } catch (CameraUseCaseAdapter.CameraException ignore) {
+            }
+        });
 
         ImageCapture.OnImageCapturedCallback callback = mock(
                 ImageCapture.OnImageCapturedCallback.class);
         FakeCameraControl fakeCameraControl =
-                ((FakeCameraControl) mFakeCamera.getCameraControlInternal());
+                ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
         fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
             // Notify the failure after the capture request has been successfully submitted
             fakeCameraControl.notifyAllRequestsOnCaptureFailed();
@@ -128,9 +153,14 @@
     public void captureWithMinLatency_jpegQualityIs95() throws InterruptedException {
         // Arrange.
         ImageCapture imageCapture = createImageCapture();
-        mInstrumentation.runOnMainSync(() -> bind(imageCapture));
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                mCameraUseCaseAdapter.addUseCases(Collections.singleton(imageCapture));
+            } catch (CameraUseCaseAdapter.CameraException ignore) {
+            }
+        });
         FakeCameraControl fakeCameraControl =
-                ((FakeCameraControl) mFakeCamera.getCameraControlInternal());
+                ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
 
         FakeCameraControl.OnNewCaptureRequestListener mockCaptureRequestListener =
                 mock(FakeCameraControl.OnNewCaptureRequestListener.class);
@@ -169,11 +199,4 @@
                 })
                 .build();
     }
-
-    // TODO(b/147698557) Should be removed when the binding of UseCase to Camera is simplified.
-    private void bind(UseCase useCase) {
-        // Sets bound camera to use case.
-        useCase.onAttach(mFakeCamera);
-        useCase.updateSuggestedResolution(new Size(640, 480));
-    }
 }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraRepositoryTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraRepositoryTest.java
new file mode 100644
index 0000000..2e0773d
--- /dev/null
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraRepositoryTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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 androidx.camera.core.impl.CameraInternal;
+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;
+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;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class LifecycleCameraRepositoryTest {
+
+    private FakeLifecycleOwner mLifecycle;
+    private LifecycleCameraRepository mRepository;
+    private CameraUseCaseAdapter mCameraUseCaseAdapter;
+    private LinkedHashSet<CameraInternal> mCameraSet;
+
+    @Before
+    public void setUp() {
+        mLifecycle = new FakeLifecycleOwner();
+        mRepository = new LifecycleCameraRepository();
+        CameraInternal camera = new FakeCamera();
+        mCameraSet = new LinkedHashSet<>(Collections.singleton(camera));
+        mCameraUseCaseAdapter = new CameraUseCaseAdapter(camera,
+                mCameraSet,
+                new FakeCameraDeviceSurfaceManager());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void throwException_ifTryingToCreateWithExistingIdentifier() {
+        LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+        LifecycleCamera secondLifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+
+        assertThat(firstLifecycleCamera).isSameInstanceAs(secondLifecycleCamera);
+    }
+
+    @Test
+    public void differentLifecycleCamerasAreCreated_forDifferentLifecycles() {
+        LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+        FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
+        LifecycleCamera secondLifecycleCamera =
+                mRepository.createLifecycleCamera(secondLifecycle,
+                        mCameraUseCaseAdapter);
+
+        assertThat(firstLifecycleCamera).isNotEqualTo(secondLifecycleCamera);
+    }
+
+    @Test
+    public void differentLifecycleCamerasAreCreated_forDifferentCameraSets() {
+        LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+
+        CameraInternal fakeCamera = new FakeCamera("other");
+        CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(fakeCamera,
+                new LinkedHashSet<>(Collections.singleton(fakeCamera)),
+                new FakeCameraDeviceSurfaceManager());
+
+        LifecycleCamera secondLifecycleCamera =
+                mRepository.createLifecycleCamera(mLifecycle,
+                        cameraUseCaseAdapter);
+
+        assertThat(firstLifecycleCamera).isNotEqualTo(secondLifecycleCamera);
+    }
+
+    @Test
+    public void useCaseIsCleared_whenLifecycleIsDestroyed() throws
+            CameraUseCaseAdapter.CameraException {
+        LifecycleCamera lifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+        FakeUseCase useCase = new FakeUseCase();
+        lifecycleCamera.bind(Collections.singleton(useCase));
+
+        assertThat(useCase.isCleared()).isFalse();
+
+        mLifecycle.destroy();
+
+        assertThat(useCase.isCleared()).isTrue();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void exception_whenCreatingWithDestroyedLifecycle() {
+        mLifecycle.destroy();
+
+        // Should throw IllegalArgumentException
+        mRepository.createLifecycleCamera(mLifecycle, mCameraUseCaseAdapter);
+    }
+
+    @Test
+    public void lifecycleCameraIsStopped_whenNewLifecycleIsStarted() {
+        // Starts first lifecycle and check LifecycleCamera active state is true.
+        LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+        mLifecycle.start();
+        assertThat(firstLifecycleCamera.isActive()).isTrue();
+
+        // Starts second lifecycle and check previous LifecycleCamera is stopped.
+        FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
+        LifecycleCamera secondLifecycleCamera =
+                mRepository.createLifecycleCamera(
+                        secondLifecycle, mCameraUseCaseAdapter);
+        secondLifecycle.start();
+        assertThat(secondLifecycleCamera.isActive()).isTrue();
+        assertThat(firstLifecycleCamera.isActive()).isFalse();
+    }
+
+    @Test
+    public void lifecycleCameraOf2ndActiveLifecycleIsStarted_when1stActiveLifecycleIsStopped() {
+        // Starts first lifecycle and check LifecycleCamera active state is true.
+        LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+        mLifecycle.start();
+        assertThat(firstLifecycleCamera.isActive()).isTrue();
+
+        // Starts second lifecycle and check previous LifecycleCamera is stopped.
+        FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
+        LifecycleCamera secondLifecycleCamera =
+                mRepository.createLifecycleCamera(
+                        secondLifecycle, mCameraUseCaseAdapter);
+        secondLifecycle.start();
+        assertThat(secondLifecycleCamera.isActive()).isTrue();
+        assertThat(firstLifecycleCamera.isActive()).isFalse();
+
+        // Stops second lifecycle and check previous LifecycleCamera is started again.
+        secondLifecycle.stop();
+        assertThat(secondLifecycleCamera.isActive()).isFalse();
+        assertThat(firstLifecycleCamera.isActive()).isTrue();
+    }
+
+    @Test
+    public void retrievesExistingCamera() {
+        LifecycleCamera lifecycleCamera = mRepository.createLifecycleCamera(
+                mLifecycle, mCameraUseCaseAdapter);
+        CameraUseCaseAdapter.CameraId cameraId = CameraUseCaseAdapter.generateCameraId(mCameraSet);
+        LifecycleCamera retrieved = mRepository.getLifecycleCamera(mLifecycle, cameraId);
+
+        assertThat(lifecycleCamera).isSameInstanceAs(retrieved);
+    }
+
+    @Test
+    public void keys() {
+        LifecycleCameraRepository.Key key0 = LifecycleCameraRepository.Key.create(mLifecycle,
+                mCameraUseCaseAdapter.getCameraId());
+        LifecycleCameraRepository.Key key1 = LifecycleCameraRepository.Key.create(mLifecycle,
+                CameraUseCaseAdapter.generateCameraId(mCameraSet));
+
+        Map<LifecycleCameraRepository.Key, LifecycleOwner> map = new HashMap<>();
+        map.put(key0, mLifecycle);
+        assertThat(map).containsKey(key1);
+
+        assertThat(key0).isEqualTo(key1);
+    }
+}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraTest.java
new file mode 100644
index 0000000..0ac18b8
--- /dev/null
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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 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.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;
+import java.util.LinkedHashSet;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LifecycleCameraTest {
+    private LifecycleCamera mLifecycleCamera;
+    private FakeLifecycleOwner mLifecycleOwner;
+    private CameraUseCaseAdapter mCameraUseCaseAdapter;
+    private FakeCamera mFakeCamera;
+    private FakeUseCase mFakeUseCase;
+
+    @Before
+    public void setUp() {
+        mLifecycleOwner = new FakeLifecycleOwner();
+        mFakeCamera = new FakeCamera();
+        mCameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                new LinkedHashSet<>(Collections.singleton(mFakeCamera)),
+                new FakeCameraDeviceSurfaceManager());
+        mFakeUseCase = new FakeUseCase();
+    }
+
+    @Test
+    public void lifecycleCameraCanBeMadeObserverOfLifecycle() {
+        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
+
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
+    }
+
+    @Test
+    public void lifecycleCameraCanStopObservingALifecycle() {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
+
+        mLifecycleCamera.release();
+
+        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void lifecycleCameraCanBeReleasedMultipleTimes() {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        mLifecycleCamera.release();
+        mLifecycleCamera.release();
+    }
+
+    @Test
+    public void lifecycleStart_triggersOnActive() {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        mLifecycleOwner.start();
+
+        assertThat(mLifecycleCamera.isActive()).isTrue();
+    }
+
+    @Test
+    public void lifecycleStop_triggersOnInactive() {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        mLifecycleOwner.start();
+
+        mLifecycleOwner.stop();
+
+        assertThat(mLifecycleCamera.isActive()).isFalse();
+    }
+
+    @Test
+    public void lifecycleStart_doesNotTriggerOnActiveIfSuspended() {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        mLifecycleCamera.suspend();
+        mLifecycleOwner.start();
+
+        assertThat(mLifecycleCamera.isActive()).isFalse();
+    }
+
+    @Test
+    public void unsuspendOfStartedLifecycle_triggersOnActive() {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+        mLifecycleCamera.suspend();
+        mLifecycleOwner.start();
+        mLifecycleCamera.unsuspend();
+
+        assertThat(mLifecycleCamera.isActive()).isTrue();
+    }
+
+    @Test
+    public void bind_willBindToCameraInternal() throws CameraUseCaseAdapter.CameraException {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+        mLifecycleOwner.start();
+
+        mLifecycleCamera.bind(Collections.singleton(mFakeUseCase));
+
+        assertThat(mFakeCamera.getAttachedUseCases()).containsExactly(mFakeUseCase);
+    }
+
+    @Test
+    public void unbind_willUnbindFromCameraInternal() throws CameraUseCaseAdapter.CameraException {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+        mLifecycleOwner.start();
+
+        mLifecycleCamera.bind(Collections.singleton(mFakeUseCase));
+        mLifecycleCamera.unbind(Collections.singletonList(mFakeUseCase));
+
+        assertThat(mFakeCamera.getAttachedUseCases()).isEmpty();
+    }
+
+    @Test
+    public void unbindAll_willUnbindFromCameraInternal()
+            throws CameraUseCaseAdapter.CameraException {
+        mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+        mLifecycleOwner.start();
+
+        mLifecycleCamera.bind(Collections.singleton(mFakeUseCase));
+        mLifecycleCamera.unbindAll();
+
+        assertThat(mFakeCamera.getAttachedUseCases()).isEmpty();
+    }
+}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorLifecycleControllerTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorLifecycleControllerTest.java
deleted file mode 100644
index 07ac7d0..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorLifecycleControllerTest.java
+++ /dev/null
@@ -1,106 +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.times;
-import static org.mockito.Mockito.verify;
-
-import androidx.camera.core.impl.UseCaseMediator;
-import androidx.camera.testing.fakes.FakeLifecycleOwner;
-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 org.mockito.Mockito;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class UseCaseMediatorLifecycleControllerTest {
-    private final UseCaseMediator.StateChangeCallback mMockCallback =
-            Mockito.mock(UseCaseMediator.StateChangeCallback.class);
-    private UseCaseMediatorLifecycleController mUseCaseMediatorLifecycleController;
-    private FakeLifecycleOwner mLifecycleOwner;
-
-    @Before
-    public void setUp() {
-        mLifecycleOwner = new FakeLifecycleOwner();
-    }
-
-    @Test
-    public void mediatorCanBeMadeObserverOfLifecycle() {
-        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
-
-        mUseCaseMediatorLifecycleController =
-                new UseCaseMediatorLifecycleController(
-                        mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-
-        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void mediatorCanStopObservingALifeCycle() {
-        mUseCaseMediatorLifecycleController =
-                new UseCaseMediatorLifecycleController(
-                        mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
-
-        mUseCaseMediatorLifecycleController.release();
-
-        assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
-    }
-
-    @Test
-    public void mediatorCanBeReleasedMultipleTimes() {
-        mUseCaseMediatorLifecycleController =
-                new UseCaseMediatorLifecycleController(
-                        mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-
-        mUseCaseMediatorLifecycleController.release();
-        mUseCaseMediatorLifecycleController.release();
-    }
-
-    @Test
-    public void lifecycleStart_triggersOnActive() {
-        mUseCaseMediatorLifecycleController =
-                new UseCaseMediatorLifecycleController(
-                        mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-        mUseCaseMediatorLifecycleController.getUseCaseMediator().setListener(mMockCallback);
-
-        mLifecycleOwner.start();
-
-        verify(mMockCallback, times(1))
-                .onActive(mUseCaseMediatorLifecycleController.getUseCaseMediator());
-    }
-
-    @Test
-    public void lifecycleStop_triggersOnInactive() {
-        mUseCaseMediatorLifecycleController =
-                new UseCaseMediatorLifecycleController(
-                        mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-        mUseCaseMediatorLifecycleController.getUseCaseMediator().setListener(mMockCallback);
-        mLifecycleOwner.start();
-
-        mLifecycleOwner.stop();
-
-        verify(mMockCallback, times(1))
-                .onInactive(mUseCaseMediatorLifecycleController.getUseCaseMediator());
-    }
-}
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
deleted file mode 100644
index 46f919a..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java
+++ /dev/null
@@ -1,173 +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 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;
-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;
-import java.util.Map;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class UseCaseMediatorRepositoryTest {
-
-    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
-    public void repositoryStartsEmpty() {
-        assertThat(mUseCasesMap).isEmpty();
-    }
-
-    @Test
-    public void newUseCaseMediatorIsCreated_whenNoMediatorExistsForLifecycleInRepository() {
-        UseCaseMediatorLifecycleController mediator = mRepository.getOrCreateUseCaseMediator(
-                mLifecycle);
-
-        assertThat(mUseCasesMap).containsExactly(mLifecycle, mediator);
-    }
-
-    @Test
-    public void existingUseCaseMediatorIsReturned_whenMediatorExistsForLifecycleInRepository() {
-        UseCaseMediatorLifecycleController firstMediator = mRepository.getOrCreateUseCaseMediator(
-                mLifecycle);
-        UseCaseMediatorLifecycleController secondMediator = mRepository.getOrCreateUseCaseMediator(
-                mLifecycle);
-
-        assertThat(firstMediator).isSameInstanceAs(secondMediator);
-        assertThat(mUseCasesMap).containsExactly(mLifecycle, firstMediator);
-    }
-
-    @Test
-    public void differentUseCaseMediatorsAreCreated_forDifferentLifecycles() {
-        UseCaseMediatorLifecycleController firstMediator = mRepository.getOrCreateUseCaseMediator(
-                mLifecycle);
-        FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
-        UseCaseMediatorLifecycleController secondMediator =
-                mRepository.getOrCreateUseCaseMediator(secondLifecycle);
-
-        assertThat(mUseCasesMap)
-                .containsExactly(mLifecycle, firstMediator, secondLifecycle, secondMediator);
-    }
-
-    @Test
-    public void useCaseMediatorObservesLifecycle() {
-        mRepository.getOrCreateUseCaseMediator(mLifecycle);
-
-        // One observer is the use case mediator. The other observer removes the use case from the
-        // repository when the lifecycle is destroyed.
-        assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
-    }
-
-    @Test
-    public void useCaseMediatorIsRemovedFromRepository_whenLifecycleIsDestroyed() {
-        mRepository.getOrCreateUseCaseMediator(mLifecycle);
-        mLifecycle.destroy();
-
-        assertThat(mUseCasesMap).isEmpty();
-    }
-
-    @Test
-    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();
-
-        assertThat(useCase.isCleared()).isTrue();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void exception_whenCreatingWithDestroyedLifecycle() {
-        mLifecycle.destroy();
-
-        // Should throw IllegalArgumentException
-        mRepository.getOrCreateUseCaseMediator(mLifecycle);
-    }
-
-    @Test
-    public void useCaseMediatorIsStopped_whenNewLifecycleIsStarted() {
-        // Starts first lifecycle and check UseCaseMediator active state is true.
-        UseCaseMediatorLifecycleController firstController = mRepository.getOrCreateUseCaseMediator(
-                mLifecycle);
-        mLifecycle.start();
-        assertThat(firstController.getUseCaseMediator().isActive()).isTrue();
-
-        // Starts second lifecycle and check previous UseCaseMediator is stopped.
-        FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
-        UseCaseMediatorLifecycleController secondController =
-                mRepository.getOrCreateUseCaseMediator(
-                        secondLifecycle);
-        secondLifecycle.start();
-        assertThat(secondController.getUseCaseMediator().isActive()).isTrue();
-        assertThat(firstController.getUseCaseMediator().isActive()).isFalse();
-    }
-
-    @Test
-    public void useCaseMediatorOf2ndActiveLifecycleIsStarted_when1stActiveLifecycleIsStopped() {
-        // Starts first lifecycle and check UseCaseMediator active state is true.
-        UseCaseMediatorLifecycleController firstController = mRepository.getOrCreateUseCaseMediator(
-                mLifecycle);
-        mLifecycle.start();
-        assertThat(firstController.getUseCaseMediator().isActive()).isTrue();
-
-        // Starts second lifecycle and check previous UseCaseMediator is stopped.
-        FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
-        UseCaseMediatorLifecycleController secondController =
-                mRepository.getOrCreateUseCaseMediator(
-                        secondLifecycle);
-        secondLifecycle.start();
-        assertThat(secondController.getUseCaseMediator().isActive()).isTrue();
-        assertThat(firstController.getUseCaseMediator().isActive()).isFalse();
-
-        // Stops second lifecycle and check previous UseCaseMediator is started again.
-        secondLifecycle.stop();
-        assertThat(secondController.getUseCaseMediator().isActive()).isFalse();
-        assertThat(firstController.getUseCaseMediator().isActive()).isTrue();
-    }
-}
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
deleted file mode 100644
index 2dec264..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core.impl;
-
-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;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Collections;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class UseCaseMediatorTest {
-    private final UseCaseMediator.StateChangeCallback mMockCallback =
-            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() {
-        FakeUseCaseConfig fakeUseCaseConfig = new FakeUseCaseConfig.Builder()
-                .setTargetName("fakeUseCaseConfig")
-                .getUseCaseConfig();
-        FakeOtherUseCaseConfig fakeOtherUseCaseConfig =
-                new FakeOtherUseCaseConfig.Builder()
-                        .setTargetName("fakeOtherUseCaseConfig")
-                        .getUseCaseConfig();
-        mCameraUseCaseAdapter = new CameraUseCaseAdapter(new FakeCamera(),
-                new FakeCameraDeviceSurfaceManager());
-        mUseCaseMediator = new UseCaseMediator();
-        mFakeUseCase = new FakeUseCase(fakeUseCaseConfig);
-        mFakeOtherUseCase = new FakeOtherUseCase(fakeOtherUseCaseConfig);
-    }
-
-    @Test
-    public void mediatorStartsEmpty() {
-        assertThat(mUseCaseMediator.getUseCases()).isEmpty();
-    }
-
-    @Test
-    public void newUseCaseIsAdded_whenNoneExistsInMediator() {
-        assertThat(mUseCaseMediator.addUseCase(mFakeUseCase)).isTrue();
-        assertThat(mUseCaseMediator.getUseCases()).containsExactly(mFakeUseCase);
-    }
-
-    @Test
-    public void multipleUseCases_canBeAdded() {
-        assertThat(mUseCaseMediator.addUseCase(mFakeUseCase)).isTrue();
-        assertThat(mUseCaseMediator.addUseCase(mFakeOtherUseCase)).isTrue();
-
-        assertThat(mUseCaseMediator.getUseCases()).containsExactly(mFakeUseCase, mFakeOtherUseCase);
-    }
-
-    @Test
-    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()
-            throws CameraUseCaseAdapter.CameraException {
-        mUseCaseMediator.addUseCase(mFakeUseCase);
-        mCameraUseCaseAdapter.attachUseCases(Collections.singleton(mFakeUseCase));
-
-        assertThat(mFakeUseCase.isCleared()).isFalse();
-
-        mUseCaseMediator.destroy();
-
-        assertThat(mFakeUseCase.isCleared()).isTrue();
-    }
-
-    @Test
-    public void useCaseRemoved_afterRemovedCalled() {
-        mUseCaseMediator.addUseCase(mFakeUseCase);
-
-        mUseCaseMediator.removeUseCase(mFakeUseCase);
-
-        assertThat(mUseCaseMediator.getUseCases()).isEmpty();
-    }
-
-    @Test
-    public void listenerOnMediatorActive_ifUseCaseMediatorStarted() {
-        mUseCaseMediator.setListener(mMockCallback);
-        mUseCaseMediator.start();
-
-        verify(mMockCallback, times(1)).onActive(mUseCaseMediator);
-    }
-
-    @Test
-    public void listenerOnMediatorInactive_ifUseCaseMediatorStopped() {
-        mUseCaseMediator.setListener(mMockCallback);
-        mUseCaseMediator.stop();
-
-        verify(mMockCallback, times(1)).onInactive(mUseCaseMediator);
-    }
-
-    @Test
-    public void setListener_replacesPreviousListener() {
-        mUseCaseMediator.setListener(mMockCallback);
-        mUseCaseMediator.setListener(null);
-
-        mUseCaseMediator.start();
-        verify(mMockCallback, never()).onActive(mUseCaseMediator);
-    }
-}
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
index ba896c6..75bd8f0 100644
--- 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
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import androidx.camera.core.impl.CameraInternal;
 import androidx.camera.testing.fakes.FakeCamera;
 import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
 import androidx.camera.testing.fakes.FakeUseCase;
@@ -29,6 +30,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.Collections;
+import java.util.LinkedHashSet;
 
 /** JUnit test cases for {@link CameraUseCaseAdapter} class. */
 @SmallTest
@@ -36,31 +38,73 @@
 public class CameraUseCaseAdapterTest {
     FakeCameraDeviceSurfaceManager mFakeCameraDeviceSurfaceManager;
     FakeCamera mFakeCamera;
+    LinkedHashSet<CameraInternal> mFakeCameraSet = new LinkedHashSet<>();
 
     @Before
     public void setUp() {
         mFakeCameraDeviceSurfaceManager = new FakeCameraDeviceSurfaceManager();
-        mFakeCamera =  new FakeCamera();
+        mFakeCamera = new FakeCamera();
+        mFakeCameraSet.add(mFakeCamera);
     }
 
     @Test
     public void attachUseCases() throws CameraUseCaseAdapter.CameraException {
         CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraSet,
                 mFakeCameraDeviceSurfaceManager);
         FakeUseCase fakeUseCase = new FakeUseCase();
-        cameraUseCaseAdapter.attachUseCases(Collections.singleton(fakeUseCase));
+        cameraUseCaseAdapter.addUseCases(Collections.singleton(fakeUseCase));
 
         assertThat(fakeUseCase.getCamera()).isEqualTo(mFakeCamera);
+        assertThat(mFakeCamera.getAttachedUseCases()).containsExactly(fakeUseCase);
     }
 
     @Test
     public void detachUseCases() throws CameraUseCaseAdapter.CameraException {
         CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraSet,
                 mFakeCameraDeviceSurfaceManager);
         FakeUseCase fakeUseCase = new FakeUseCase();
-        cameraUseCaseAdapter.attachUseCases(Collections.singleton(fakeUseCase));
-        cameraUseCaseAdapter.detachUseCases(Collections.singleton(fakeUseCase));
+        cameraUseCaseAdapter.addUseCases(Collections.singleton(fakeUseCase));
+        cameraUseCaseAdapter.removeUseCases(Collections.singleton(fakeUseCase));
 
         assertThat(fakeUseCase.getCamera()).isNull();
     }
+
+    @Test
+    public void closeCameraUseCaseAdapter() throws CameraUseCaseAdapter.CameraException {
+        CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraSet,
+                mFakeCameraDeviceSurfaceManager);
+        FakeUseCase fakeUseCase = new FakeUseCase();
+        cameraUseCaseAdapter.addUseCases(Collections.singleton(fakeUseCase));
+        cameraUseCaseAdapter.detachUseCases();
+
+        assertThat(fakeUseCase.getCamera()).isEqualTo(mFakeCamera);
+        assertThat(mFakeCamera.getAttachedUseCases()).isEmpty();
+    }
+
+    @Test
+    public void cameraIdEquals() {
+        CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraSet,
+                mFakeCameraDeviceSurfaceManager);
+
+        CameraUseCaseAdapter.CameraId otherCameraId =
+                CameraUseCaseAdapter.generateCameraId(mFakeCameraSet);
+
+        assertThat(cameraUseCaseAdapter.getCameraId().equals(otherCameraId)).isTrue();
+    }
+
+    @Test
+    public void cameraEquivalent() {
+        CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraSet,
+                mFakeCameraDeviceSurfaceManager);
+
+        CameraUseCaseAdapter otherCameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+                mFakeCameraSet,
+                mFakeCameraDeviceSurfaceManager);
+        assertThat(cameraUseCaseAdapter.isEquivalent(otherCameraUseCaseAdapter)).isTrue();
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
index 7b31439..71a7d11 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
@@ -71,6 +71,25 @@
     @UseExperimental(markerClass = ExperimentalCameraFilter.class)
     @NonNull
     public CameraInternal select(@NonNull LinkedHashSet<CameraInternal> cameras) {
+        return filter(cameras).iterator().next();
+    }
+
+    /**
+     * Filters the input cameras using the {@link CameraFilter} assigned to the selector.
+     *
+     * <p>The camera filtered must be contained in the input set. Otherwise it will throw an
+     * exception.
+     *
+     * @param cameras The camera set being filtered.
+     * @return The remain set of cameras.
+     * @throws IllegalArgumentException If there's no available camera after being filtered or
+     *                                  the filtered camera ids aren't contained in the input set.
+     * @hide
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @UseExperimental(markerClass = ExperimentalCameraFilter.class)
+    @NonNull
+    public LinkedHashSet<CameraInternal> filter(@NonNull LinkedHashSet<CameraInternal> cameras) {
         LinkedHashSet<Camera> camerasCopy = new LinkedHashSet<>(cameras);
         LinkedHashSet<Camera> resultCameras = new LinkedHashSet<>(cameras);
         for (CameraFilter filter : mCameraFilterSet) {
@@ -85,7 +104,12 @@
             camerasCopy.retainAll(resultCameras);
         }
 
-        return (CameraInternal) resultCameras.iterator().next();
+        LinkedHashSet<CameraInternal> returnCameras = new LinkedHashSet<>();
+        for (Camera camera : resultCameras) {
+            returnCameras.add((CameraInternal) camera);
+        }
+
+        return returnCameras;
     }
 
     /**
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 f73f4eb..739475c 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
@@ -19,12 +19,10 @@
 import android.app.Application;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Rect;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
 import android.util.Log;
-import android.util.Size;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.MainThread;
@@ -39,17 +37,14 @@
 import androidx.camera.core.impl.CameraInternal;
 import androidx.camera.core.impl.CameraRepository;
 import androidx.camera.core.impl.CameraThreadConfig;
-import androidx.camera.core.impl.SurfaceConfig;
 import androidx.camera.core.impl.UseCaseConfig;
 import androidx.camera.core.impl.UseCaseConfigFactory;
-import androidx.camera.core.impl.UseCaseMediator;
 import androidx.camera.core.impl.utils.Threads;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.FutureCallback;
 import androidx.camera.core.impl.utils.futures.FutureChain;
 import androidx.camera.core.impl.utils.futures.Futures;
-import androidx.camera.core.internal.UseCaseOccupancy;
-import androidx.camera.core.internal.ViewPorts;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.os.HandlerCompat;
 import androidx.core.util.Preconditions;
@@ -59,12 +54,10 @@
 import com.google.common.util.concurrent.ListenableFuture;
 
 import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -172,9 +165,10 @@
 
     final CameraRepository mCameraRepository = new CameraRepository();
     private final Object mInitializeLock = new Object();
-    private final UseCaseMediatorRepository
-            mUseCaseMediatorRepository = new UseCaseMediatorRepository();
+
     private final CameraXConfig mCameraXConfig;
+    private final LifecycleCameraRepository
+            mLifecycleCameraRepository = new LifecycleCameraRepository();
     private final Executor mCameraExecutor;
     private final Handler mSchedulerHandler;
     @Nullable
@@ -294,26 +288,8 @@
         Threads.checkMainThread();
         CameraX cameraX = checkInitialized();
         // TODO(b/153096869): override UseCase's target rotation.
-
-        UseCaseMediatorLifecycleController useCaseMediatorLifecycleController =
-                cameraX.getOrCreateUseCaseMediator(lifecycleOwner);
-        UseCaseMediator useCaseMediatorToBind =
-                useCaseMediatorLifecycleController.getUseCaseMediator();
-
-        Collection<UseCaseMediatorLifecycleController> controllers =
-                cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-        for (UseCase useCase : useCases) {
-            for (UseCaseMediatorLifecycleController controller : controllers) {
-                UseCaseMediator useCaseMediator = controller.getUseCaseMediator();
-                if (useCaseMediator.contains(useCase) && useCaseMediator != useCaseMediatorToBind) {
-                    throw new IllegalStateException(
-                            String.format(
-                                    "Use case %s already bound to a different lifecycle.",
-                                    useCase));
-                }
-            }
-        }
-
+        // TODO(b/154939118) The filter appending should be removed after extensions are moved to
+        //  the CheckedCameraInternal
         CameraSelector.Builder selectorBuilder =
                 CameraSelector.Builder.fromSelector(cameraSelector);
         // Append the camera filter required internally if there's any.
@@ -326,68 +302,53 @@
             }
         }
 
-        // Try to get the camera before binding to the use case, and throw IllegalArgumentException
-        // if the camera not found.
-        CameraInternal camera = CameraX.getCameraWithCameraSelector(selectorBuilder.build());
+        CameraSelector modifiedSelector = selectorBuilder.build();
 
-        if (useCases.length == 0) {
-            return camera;
-        }
+        LinkedHashSet<CameraInternal> cameraInternals =
+                modifiedSelector.filter(cameraX.mCameraRepository.getCameras());
+        CameraUseCaseAdapter.CameraId cameraId =
+                CameraUseCaseAdapter.generateCameraId(cameraInternals);
 
-        List<UseCase> originalUseCases = new ArrayList<>();
+        LifecycleCamera lifecycleCameraToBind =
+                cameraX.mLifecycleCameraRepository.getLifecycleCamera(lifecycleOwner, cameraId);
 
-        // Collect original use cases attached to the camera
-        for (UseCase useCase : useCaseMediatorToBind.getUseCases()) {
-            CameraInternal attachedCamera = useCase.getCamera();
-            if (attachedCamera != null) {
-                if (camera.equals(attachedCamera)) {
-                    originalUseCases.add(useCase);
+        Collection<LifecycleCamera> lifecycleCameras =
+                cameraX.mLifecycleCameraRepository.getLifecycleCameras();
+        for (UseCase useCase : useCases) {
+            for (LifecycleCamera lifecycleCamera : lifecycleCameras) {
+                if (lifecycleCamera.isBound(useCase)
+                        && lifecycleCamera != lifecycleCameraToBind) {
+                    throw new IllegalStateException(
+                            String.format(
+                                    "Use case %s already bound to a different lifecycle.",
+                                    useCase));
                 }
             }
         }
 
-        // Only do resolution calculation if UseCases were attached
-        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");
+        // Try to get the camera before binding to the use case, and throw IllegalArgumentException
+        // if the camera not found.
+        if (lifecycleCameraToBind == null) {
+            lifecycleCameraToBind =
+                    cameraX.mLifecycleCameraRepository.createLifecycleCamera(lifecycleOwner,
+                            new CameraUseCaseAdapter(cameraInternals.iterator().next(),
+                                    cameraInternals,
+                                    cameraX.getCameraDeviceSurfaceManager()));
         }
 
-        Map<UseCase, Size> suggestedResolutionsMap = calculateSuggestedResolutions(
-                camera.getCameraInfoInternal(),
-                originalUseCases,
-                Arrays.asList(useCases));
 
-        if (viewPort != null) {
-            // Calculate crop rect if view port is provided.
-            Map<UseCase, Rect> cropRectMap = ViewPorts.calculateViewPortRects(
-                    camera.getCameraControlInternal().getSensorRect(),
-                    viewPort.getAspectRatio(),
-                    camera.getCameraInfoInternal().getSensorRotationDegrees(
-                            viewPort.getRotation()),
-                    viewPort.getScaleType(),
-                    viewPort.getLayoutDirection(),
-                    suggestedResolutionsMap);
-            for (UseCase useCase : useCases) {
-                useCase.setViewPortCropRect(cropRectMap.get(useCase));
-            }
+        if (useCases.length == 0) {
+            return lifecycleCameraToBind;
         }
 
-        // At this point the binding will succeed since all the calculations are done
-        // Do all binding related work
-        for (UseCase useCase : useCases) {
-            useCase.onAttach(camera);
-            useCase.updateSuggestedResolution(
-                    Preconditions.checkNotNull(suggestedResolutionsMap.get(useCase)));
-
-            // Update the UseCaseMediator
-            useCaseMediatorToBind.addUseCase(useCase);
+        try {
+            lifecycleCameraToBind.getCameraUseCaseAdapter().setViewPort(viewPort);
+            lifecycleCameraToBind.bind(Arrays.asList(useCases));
+        } catch (CameraUseCaseAdapter.CameraException e) {
+            throw new IllegalArgumentException(e.getMessage());
         }
 
-        useCaseMediatorLifecycleController.notifyState();
-
-        return camera;
+        return lifecycleCameraToBind;
     }
 
     /**
@@ -403,12 +364,9 @@
     public static boolean isBound(@NonNull UseCase useCase) {
         CameraX cameraX = checkInitialized();
 
-        Collection<UseCaseMediatorLifecycleController> controllers =
-                cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-
-        for (UseCaseMediatorLifecycleController controller : controllers) {
-            UseCaseMediator useCaseMediator = controller.getUseCaseMediator();
-            if (useCaseMediator.contains(useCase)) {
+        for (LifecycleCamera lifecycleCamera :
+                cameraX.mLifecycleCameraRepository.getLifecycleCameras()) {
+            if (lifecycleCamera.isBound(useCase)) {
                 return true;
             }
         }
@@ -436,26 +394,9 @@
         Threads.checkMainThread();
         CameraX cameraX = checkInitialized();
 
-        Collection<UseCaseMediatorLifecycleController> useCaseMediators =
-                cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-
-        for (UseCase useCase : useCases) {
-            // Remove the UseCase from the mediator.
-            boolean wasUnbound = false;
-            for (UseCaseMediatorLifecycleController useCaseMediatorLifecycleController :
-                    useCaseMediators) {
-                if (useCaseMediatorLifecycleController.getUseCaseMediator().removeUseCase(
-                        useCase)) {
-                    wasUnbound = true;
-                }
-            }
-
-            // Unbind the UseCase from the currently bound camera if it is bound
-            CameraInternal attachedCamera = useCase.getCamera();
-            if (wasUnbound && attachedCamera != null) {
-                useCase.onDetach(attachedCamera);
-                useCase.onDestroy();
-            }
+        for (LifecycleCamera lifecycleCamera :
+                cameraX.mLifecycleCameraRepository.getLifecycleCameras()) {
+            lifecycleCamera.unbind(Arrays.asList(useCases));
         }
     }
 
@@ -472,18 +413,10 @@
         Threads.checkMainThread();
         CameraX cameraX = checkInitialized();
 
-        Collection<UseCaseMediatorLifecycleController> useCaseMediators =
-                cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-
-        List<UseCase> useCases = new ArrayList<>();
-        for (UseCaseMediatorLifecycleController useCaseMediatorLifecycleController :
-                useCaseMediators) {
-            UseCaseMediator useCaseMediator =
-                    useCaseMediatorLifecycleController.getUseCaseMediator();
-            useCases.addAll(useCaseMediator.getUseCases());
+        for (LifecycleCamera lifecycleCamera :
+                cameraX.mLifecycleCameraRepository.getLifecycleCameras()) {
+            lifecycleCamera.unbindAll();
         }
-
-        unbind(useCases.toArray(new UseCase[0]));
     }
 
     /**
@@ -771,12 +704,12 @@
 
         Collection<UseCase> activeUseCases = null;
 
-        Collection<UseCaseMediatorLifecycleController> controllers =
-                cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
+        Collection<LifecycleCamera> lifecycleCameras =
+                cameraX.mLifecycleCameraRepository.getLifecycleCameras();
 
-        for (UseCaseMediatorLifecycleController controller : controllers) {
-            if (controller.getUseCaseMediator().isActive()) {
-                activeUseCases = controller.getUseCaseMediator().getUseCases();
+        for (LifecycleCamera lifecycleCamera : lifecycleCameras) {
+            if (lifecycleCamera.isActive()) {
+                activeUseCases = lifecycleCamera.getUseCases();
                 break;
             }
         }
@@ -935,45 +868,6 @@
 
     }
 
-    private static Map<UseCase, Size> calculateSuggestedResolutions(
-            @NonNull CameraInfoInternal cameraInfo,
-            @NonNull List<UseCase> originalUseCases, @NonNull List<UseCase> newUseCases) {
-        List<SurfaceConfig> existingSurfaces = new ArrayList<>();
-        String cameraId = cameraInfo.getCameraId();
-
-        // Collect original use cases for different camera devices
-        for (UseCase useCase : originalUseCases) {
-            SurfaceConfig surfaceConfig =
-                    getSurfaceManager().transformSurfaceConfig(cameraId,
-                            useCase.getImageFormat(),
-                            useCase.getAttachedSurfaceResolution());
-            existingSurfaces.add(surfaceConfig);
-        }
-
-        Map<UseCaseConfig<?>, UseCase> configToUseCaseMap = new HashMap<>();
-        for (UseCase useCase : newUseCases) {
-            UseCaseConfig.Builder<?, ?, ?> defaultBuilder = useCase.getDefaultBuilder(cameraInfo);
-
-            // 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 = getSurfaceManager()
-                .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;
-    }
-
     /**
      * Returns the {@link CameraDeviceSurfaceManager} instance.
      *
@@ -1121,12 +1015,6 @@
         }
     }
 
-    private UseCaseMediatorLifecycleController getOrCreateUseCaseMediator(
-            LifecycleOwner lifecycleOwner) {
-        return mUseCaseMediatorRepository.getOrCreateUseCaseMediator(
-                lifecycleOwner, useCaseMediator -> useCaseMediator.setListener(mCameraRepository));
-    }
-
     private CameraRepository getCameraRepository() {
         return mCameraRepository;
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCamera.java b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCamera.java
new file mode 100644
index 0000000..28bc9bf
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCamera.java
@@ -0,0 +1,220 @@
+/*
+ * 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.internal.CameraUseCaseAdapter;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.Lifecycle.State;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A {@link CameraUseCaseAdapter} whose starting and stopping is controlled by a
+ *  {@link Lifecycle}.
+ */
+final class LifecycleCamera implements LifecycleObserver, Camera {
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    // The lifecycle that controls the LifecycleCamera
+    private final LifecycleOwner mLifecycleOwner;
+
+    private final CameraUseCaseAdapter mCameraUseCaseAdapter;
+
+    @GuardedBy("mLock")
+    private volatile boolean mIsActive = false;
+
+    @GuardedBy("mLock")
+    private boolean mSuspended = false;
+
+    @GuardedBy("mLock")
+    private boolean mReleased = false;
+
+    /**
+     * Wraps an existing {@link CameraUseCaseAdapter} so it is controlled by lifecycle transitions.
+     */
+    LifecycleCamera(LifecycleOwner lifecycleOwner, CameraUseCaseAdapter cameraUseCaseAdaptor) {
+        mLifecycleOwner = lifecycleOwner;
+        mCameraUseCaseAdapter = cameraUseCaseAdaptor;
+        lifecycleOwner.getLifecycle().addObserver(this);
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_START)
+    public void onStart(LifecycleOwner lifecycleOwner) {
+        synchronized (mLock) {
+            if (!mSuspended && !mReleased) {
+                mCameraUseCaseAdapter.attachUseCases();
+                mIsActive = true;
+            }
+        }
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    public void onStop(LifecycleOwner lifecycleOwner) {
+        synchronized (mLock) {
+            if (!mSuspended && !mReleased) {
+                mCameraUseCaseAdapter.detachUseCases();
+                mIsActive = false;
+            }
+        }
+    }
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+    public void onDestroy(LifecycleOwner lifecycleOwner) {
+        synchronized (mLock) {
+            mCameraUseCaseAdapter.removeUseCases(mCameraUseCaseAdapter.getUseCases());
+        }
+    }
+
+    /**
+     * Suspend the camera so that it ignore lifecycle events.
+     *
+     * <p> This will also close the {@link CameraUseCaseAdapter}.
+     *
+     * <p> This will be idempotent if the camera is already suspended.
+     */
+    public void suspend() {
+        synchronized (mLock) {
+            if (mSuspended) {
+                return;
+            }
+
+            onStop(mLifecycleOwner);
+            mSuspended = true;
+        }
+    }
+
+    /**
+     * Unsuspend the camera so it will start listening to lifecycle events.
+     *
+     * <p> This will also open the {@link CameraUseCaseAdapter} if the lifecycle is in a STARTED
+     * state or above.
+     *
+     * <p> This will be idempotent if the camera is already in an unsuspended state.
+     */
+    public void unsuspend() {
+        synchronized (mLock) {
+            if (!mSuspended) {
+                return;
+            }
+
+            mSuspended = false;
+            if (mLifecycleOwner.getLifecycle().getCurrentState().isAtLeast(State.STARTED)) {
+                onStart(mLifecycleOwner);
+            }
+        }
+    }
+
+    // TODO(b/154939118) remove when Extension.setExtension() is implemented since there no
+    //  longer is a need to check if the camera is active.
+    public boolean isActive() {
+        synchronized (mLock) {
+            return mIsActive;
+        }
+    }
+
+    public boolean isBound(@NonNull UseCase useCase) {
+        synchronized (mLock) {
+            return mCameraUseCaseAdapter.getUseCases().contains(useCase);
+        }
+    }
+
+    @NonNull
+    public List<UseCase> getUseCases() {
+        synchronized (mLock) {
+            return Collections.unmodifiableList(mCameraUseCaseAdapter.getUseCases());
+        }
+    }
+
+    public CameraUseCaseAdapter getCameraUseCaseAdapter() {
+        return mCameraUseCaseAdapter;
+    }
+
+    /**
+     * Bind the UseCases to the lifecycle camera.
+     *
+     * <>This will attach the UseCases to the CameraUseCaseAdapter if successful.
+     *
+     * @throws CameraUseCaseAdapter.CameraException if unable to attach the UseCase to the camera.
+     */
+    void bind(Collection<UseCase> useCases) throws CameraUseCaseAdapter.CameraException {
+        synchronized (mLock) {
+            mCameraUseCaseAdapter.addUseCases(useCases);
+            for (UseCase useCase : useCases) {
+                useCase.notifyState();
+            }
+        }
+    }
+
+    /**
+     * Unbind the UseCases from the lifecycle camera.
+     *
+     * <>This will detach the UseCases from the CameraUseCaseAdapter.
+     */
+    void unbind(Collection<UseCase> useCases) {
+        synchronized (mLock) {
+            mCameraUseCaseAdapter.removeUseCases(useCases);
+        }
+    }
+
+    /**
+     * Unbind all of the UseCases from the lifecycle camera.
+     *
+     * <p>This will detach all UseCases from the CameraUseCaseAdapter.
+     */
+    void unbindAll() {
+        synchronized (mLock) {
+            mCameraUseCaseAdapter.removeUseCases(mCameraUseCaseAdapter.getUseCases());
+        }
+    }
+
+    /**
+     * Stops observing lifecycle changes.
+     *
+     * <p>Once released the wrapped {@link LifecycleCamera} is still valid, but will no longer be
+     * triggered by lifecycle state transitions. In order to observe lifecycle changes again a new
+     * {@link LifecycleCamera} instance should be created.
+     *
+     * <p>Calls subsequent to the first time will do nothing.
+     */
+    void release() {
+        synchronized (mLock) {
+            mReleased = true;
+            mIsActive = false;
+            mLifecycleOwner.getLifecycle().removeObserver(this);
+        }
+    }
+
+    @NonNull
+    @Override
+    public CameraControl getCameraControl() {
+        return mCameraUseCaseAdapter.getCameraControlInternal();
+    }
+
+    @NonNull
+    @Override
+    public CameraInfo getCameraInfo() {
+        return mCameraUseCaseAdapter.getCameraInfoInternal();
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCameraRepository.java b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCameraRepository.java
new file mode 100644
index 0000000..7b155ee
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCameraRepository.java
@@ -0,0 +1,249 @@
+/*
+ * 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.annotation.Nullable;
+import androidx.camera.core.impl.CameraInternal;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.core.util.Preconditions;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.Lifecycle.State;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import com.google.auto.value.AutoValue;
+
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A repository of {@link LifecycleCamera} instances.
+ *
+ * <p> This repository maps each unique pair of {@link LifecycleOwner} and set of
+ * {@link CameraInternal} to a single LifecycleCamera.
+ *
+ * <p> The repository ensures that only a single LifecycleCamera is active at a time so if the
+ * Lifecycle of a camera starts then it will take over as the current active camera. This means
+ * that at anytime only one of the LifecycleCamera in the repo will be in the unsuspended state.
+ * All others will be suspended.
+ *
+ * <p> When the Lifecycle of the most recently active camera stops then it will make sure
+ * that the next most recently started camera become the active camera.
+ *
+ * <p> A LifecycleCamera associated with the repository can also be released from the repository.
+ * When it is released, all UseCases bound to the LifecycleCamera will be unbound and the
+ * LifecycleCamera will be released.
+ */
+final class LifecycleCameraRepository {
+    final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    final Map<Key, LifecycleCamera> mCameraMap = new HashMap<>();
+
+    @GuardedBy("mLock")
+    final Map<Key, LifecycleCameraRepositoryObserver> mLifecycleObserverMap = new HashMap<>();
+
+    @GuardedBy("mLock")
+    private final ArrayDeque<Key> mActiveCameras = new ArrayDeque<>();
+
+    /**
+     * Create a new {@link LifecycleCamera} associated with the given {@link LifecycleOwner}.
+     *
+     * <p>The {@link LifecycleCamera} is set to be an observer of the {@link
+     * LifecycleOwner}.
+     *
+     * @param lifecycleOwner       to associate with the LifecycleCamera
+     * @param cameraUseCaseAdaptor the CameraUseCaseAdapter to wrap in a LifecycleCamera
+     *
+     * @throws IllegalArgumentException if the LifecycleOwner is already in a destroyed state or
+     * if the repository already contains a LifecycleCamera that has the same LifecycleOwner and
+     * CameraInternal set as the CameraUseCaseAdapter.
+     */
+    LifecycleCamera createLifecycleCamera(
+            @NonNull LifecycleOwner lifecycleOwner,
+            @NonNull CameraUseCaseAdapter cameraUseCaseAdaptor) {
+        LifecycleCamera lifecycleCamera;
+        synchronized (mLock) {
+            Key key = Key.create(lifecycleOwner, cameraUseCaseAdaptor.getCameraId());
+            Preconditions.checkArgument(mCameraMap.get(key) == null, "LifecycleCamera already "
+                    + "exists for the given LifecycleOwner and set of cameras");
+
+            if (lifecycleOwner.getLifecycle().getCurrentState() == State.DESTROYED) {
+                throw new IllegalArgumentException(
+                        "Trying to create LifecycleCamera with destroyed lifecycle.");
+            }
+
+            // Need to add observer before creating LifecycleCamera to make sure
+            // it can be stopped before the latest active one is started.'
+            lifecycleCamera = new LifecycleCamera(lifecycleOwner, cameraUseCaseAdaptor);
+            registerCamera(key, lifecycleCamera);
+        }
+        return lifecycleCamera;
+    }
+
+    /**
+     * Get the LifecycleCamera which contains the same LifecycleOwner and a
+     * CameraUseCaseAdapter.CameraId.
+     *
+     * @return null if no such LifecycleCamera exists.
+     */
+    @Nullable
+    LifecycleCamera getLifecycleCamera(LifecycleOwner lifecycleOwner,
+            CameraUseCaseAdapter.CameraId cameraId) {
+        synchronized (mLock) {
+            return mCameraMap.get(Key.create(lifecycleOwner, cameraId));
+        }
+    }
+
+    /**
+     * Returns all the LifecycleCamera that have been created by the repository which haven't
+     * been destroyed yet.
+     */
+    Collection<LifecycleCamera> getLifecycleCameras() {
+        synchronized (mLock) {
+            return Collections.unmodifiableCollection(mCameraMap.values());
+        }
+    }
+
+    // Registers the LifecycleCamera in the repository so that the repository ensures that only one
+    // camera is active at one time.
+    private void registerCamera(Key key, LifecycleCamera lifecycleCamera) {
+        synchronized (mLock) {
+            LifecycleCameraRepositoryObserver observer =
+                    new LifecycleCameraRepositoryObserver(key, this);
+            mLifecycleObserverMap.put(key, observer);
+            mCameraMap.put(key, lifecycleCamera);
+            key.getLifecycleOwner().getLifecycle().addObserver(observer);
+        }
+    }
+
+    // Unregisters the Lifecycle from the repository so it is no longer tracked by the repository.
+    // This does not stop the camera from receiving its lifecycle events. For the LifecycleCamera
+    // to stop receiving lifecycle event it must be done manually either before or after.
+    void unregisterCamera(Key key) {
+        synchronized (mLock) {
+            setInactive(key);
+            mCameraMap.remove(key);
+            LifecycleCameraRepositoryObserver observer = mLifecycleObserverMap.remove(key);
+            if (observer != null) {
+                key.getLifecycleOwner().getLifecycle().removeObserver(observer);
+            }
+
+        }
+    }
+
+    // Sets the LifecycleCamera with the associated key as the current active camera. This will
+    // suspend all other cameras which are tracked by the repository.
+    void setActive(Key key) {
+        synchronized (mLock) {
+            LifecycleCamera camera = mCameraMap.get(key);
+            if (camera != null) {
+
+                // Only keep the last {@link LifecycleOwner} active. Stop the others.
+                if (mActiveCameras.isEmpty()) {
+                    mActiveCameras.push(key);
+                } else {
+                    Key currentActiveCamera = mActiveCameras.peek();
+                    if (currentActiveCamera != key) {
+                        Preconditions.checkNotNull(
+                                mCameraMap.get(currentActiveCamera)).suspend();
+                        mActiveCameras.push(key);
+                    }
+                }
+                camera.unsuspend();
+            }
+        }
+    }
+
+    // Removes the LifecycleCamera with the associated key from list of active cameras.
+    // If this camera was the current active camera then the next most recently active camera in
+    // the current active list will become the active camera.
+    void setInactive(Key key) {
+        synchronized (mLock) {
+            // Removes stopped lifecycleOwner from active list.
+            mActiveCameras.remove(key);
+
+            // Start up next LifecycleCamera if there are still active cameras
+            if (!mActiveCameras.isEmpty()) {
+                Preconditions.checkNotNull(
+                        mCameraMap.get(mActiveCameras.peek())).unsuspend();
+            }
+        }
+    }
+
+    /**
+     * A key for mapping a {@link LifecycleOwner} and set of {@link CameraInternal} to a
+     * {@link LifecycleCamera}.
+     */
+    @AutoValue
+    abstract static class Key {
+        static Key create(@NonNull LifecycleOwner lifecycleOwner,
+                @NonNull CameraUseCaseAdapter.CameraId cameraId) {
+            return new AutoValue_LifecycleCameraRepository_Key(lifecycleOwner, cameraId);
+        }
+
+        @NonNull
+        public abstract LifecycleOwner getLifecycleOwner();
+
+        @NonNull
+        public abstract CameraUseCaseAdapter.CameraId getCameraId();
+    }
+
+    private static class LifecycleCameraRepositoryObserver implements LifecycleObserver {
+        private final LifecycleCameraRepository mLifecycleCameraRepository;
+        private final Key mKey;
+
+        LifecycleCameraRepositoryObserver(Key key,
+                LifecycleCameraRepository lifecycleCameraRepository) {
+            mKey = key;
+            mLifecycleCameraRepository = lifecycleCameraRepository;
+        }
+
+        /**
+         * Monitors which {@link LifecycleOwner} receives an ON_START event and then stop
+         * other {@link LifecycleCamera} to keep only one active at a time.
+         */
+        @OnLifecycleEvent(Lifecycle.Event.ON_START)
+        public void onStart(LifecycleOwner lifecycleOwner) {
+            mLifecycleCameraRepository.setActive(mKey);
+        }
+
+        /**
+         * Monitors which {@link LifecycleOwner} receives an ON_STOP event.
+         */
+        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+        public void onStop(LifecycleOwner lifecycleOwner) {
+            mLifecycleCameraRepository.setInactive(mKey);
+        }
+
+        /**
+         * Monitors which {@link LifecycleOwner} receives an ON_DESTROY event and then
+         * removes any {@link LifecycleCamera} associated with it from this
+         * repository when that lifecycle is destroyed.
+         */
+        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+        public void onDestroy(LifecycleOwner lifecycleOwner) {
+            mLifecycleCameraRepository.unregisterCamera(mKey);
+        }
+    }
+}
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 7bff94e..a49dbb0 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
@@ -127,7 +127,7 @@
     protected final void updateUseCaseConfig(@NonNull UseCaseConfig<?> useCaseConfig) {
         // Attempt to retrieve builder containing defaults for this use case's config
         UseCaseConfig.Builder<?, ?, ?> defaultBuilder =
-                getDefaultBuilder(getCamera() == null ? null : getCamera().getCameraInfo());
+                getDefaultBuilder(getCamera() == null ? null : getCamera().getCameraInfoInternal());
 
         // Combine with default configuration.
         mUseCaseConfig = applyDefaults(useCaseConfig, defaultBuilder);
@@ -428,6 +428,7 @@
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     public void onAttach(@NonNull CameraInternal camera) {
+
         synchronized (mCameraLock) {
             mCamera = camera;
             addStateChangeCallback(camera);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorLifecycleController.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorLifecycleController.java
deleted file mode 100644
index b1b860a..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorLifecycleController.java
+++ /dev/null
@@ -1,107 +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.camera.core.impl.UseCaseMediator;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-
-/** A {@link UseCaseMediator} whose starting and stopping is controlled by a {@link Lifecycle}. */
-final class UseCaseMediatorLifecycleController implements LifecycleObserver {
-    private final Object mUseCaseMediatorLock = new Object();
-
-    @GuardedBy("mUseCaseMediatorLock")
-    private final UseCaseMediator mUseCaseMediator;
-
-    /** The lifecycle that controls the {@link UseCaseMediator}. */
-    private final Lifecycle mLifecycle;
-
-    /** Creates a new {@link UseCaseMediator} which gets controlled by lifecycle transitions. */
-    UseCaseMediatorLifecycleController(Lifecycle lifecycle) {
-        this(lifecycle, new UseCaseMediator());
-    }
-
-    /** Wraps an existing {@link UseCaseMediator} so it is controlled by lifecycle transitions. */
-    UseCaseMediatorLifecycleController(Lifecycle lifecycle, UseCaseMediator useCaseMediator) {
-        this.mUseCaseMediator = useCaseMediator;
-        this.mLifecycle = lifecycle;
-        lifecycle.addObserver(this);
-    }
-
-    @OnLifecycleEvent(Lifecycle.Event.ON_START)
-    public void onStart(LifecycleOwner lifecycleOwner) {
-        synchronized (mUseCaseMediatorLock) {
-            mUseCaseMediator.start();
-        }
-    }
-
-    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
-    public void onStop(LifecycleOwner lifecycleOwner) {
-        synchronized (mUseCaseMediatorLock) {
-            mUseCaseMediator.stop();
-        }
-    }
-
-    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
-    public void onDestroy(LifecycleOwner lifecycleOwner) {
-        synchronized (mUseCaseMediatorLock) {
-            mUseCaseMediator.destroy();
-        }
-    }
-
-    /**
-     * Starts the underlying {@link UseCaseMediator} so that its {@link
-     * UseCaseMediator.StateChangeCallback} can be notified.
-     *
-     * <p>This is required when the contained {@link Lifecycle} is in a STARTED state, since the
-     * default state for a {@link UseCaseMediator} is inactive. The explicit call forces a check on
-     * the actual state of the mediator.
-     */
-    void notifyState() {
-        synchronized (mUseCaseMediatorLock) {
-            if (mLifecycle.getCurrentState().isAtLeast(State.STARTED)) {
-                mUseCaseMediator.start();
-            }
-            for (UseCase useCase : mUseCaseMediator.getUseCases()) {
-                useCase.notifyState();
-            }
-        }
-    }
-
-    UseCaseMediator getUseCaseMediator() {
-        synchronized (mUseCaseMediatorLock) {
-            return mUseCaseMediator;
-        }
-    }
-
-    /**
-     * Stops observing lifecycle changes.
-     *
-     * <p>Once released the wrapped {@link UseCaseMediator} is still valid, but will no longer be
-     * triggered by lifecycle state transitions. In order to observe lifecycle changes again a new
-     * {@link UseCaseMediatorLifecycleController} instance should be created.
-     *
-     * <p>Calls subsequent to the first time will do nothing.
-     */
-    void release() {
-        mLifecycle.removeObserver(this);
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorRepository.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorRepository.java
deleted file mode 100644
index c47c40f..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorRepository.java
+++ /dev/null
@@ -1,214 +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.annotation.VisibleForTesting;
-import androidx.camera.core.impl.UseCaseMediator;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-
-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 repository of {@link UseCaseMediatorLifecycleController} instances.
- *
- * <p>Each {@link UseCaseMediatorLifecycleController} is associated with a {@link LifecycleOwner}
- * that regulates the common lifecycle shared by all the use cases in the mediator.
- */
-final class UseCaseMediatorRepository {
-    final Object mUseCasesLock = new Object();
-
-    @GuardedBy("mUseCasesLock")
-    final Map<LifecycleOwner, UseCaseMediatorLifecycleController>
-            mLifecycleToUseCaseMediatorControllerMap =
-            new HashMap<>();
-    @GuardedBy("mUseCasesLock")
-    final List<LifecycleOwner> mActiveLifecycleOwnerList = new ArrayList<>();
-    @GuardedBy("mUseCasesLock")
-    LifecycleOwner mCurrentActiveLifecycleOwner = null;
-
-    /**
-     * Gets an existing {@link UseCaseMediatorLifecycleController} associated with the given {@link
-     * LifecycleOwner}, or creates a new {@link UseCaseMediatorLifecycleController} if a mediator
-     * does not already exist.
-     *
-     * <p>The {@link UseCaseMediatorLifecycleController} is set to be an observer of the {@link
-     * LifecycleOwner}.
-     *
-     * @param lifecycleOwner to associate with the mediator
-     */
-    UseCaseMediatorLifecycleController getOrCreateUseCaseMediator(LifecycleOwner lifecycleOwner) {
-        return getOrCreateUseCaseMediator(lifecycleOwner, useCaseMediator -> {
-        });
-    }
-
-    /**
-     * Gets an existing {@link UseCaseMediatorLifecycleController} associated with the given {@link
-     * LifecycleOwner}, or creates a new {@link UseCaseMediatorLifecycleController} if a mediator
-     * does not already exist.
-     *
-     * <p>The {@link UseCaseMediatorLifecycleController} is set to be an observer of the {@link
-     * LifecycleOwner}.
-     *
-     * @param lifecycleOwner to associate with the mediator
-     * @param mediatorSetup  additional setup to do on the mediator if a new instance is created
-     */
-    UseCaseMediatorLifecycleController getOrCreateUseCaseMediator(
-            LifecycleOwner lifecycleOwner, UseCaseMediatorSetup mediatorSetup) {
-        UseCaseMediatorLifecycleController useCaseMediatorLifecycleController;
-        synchronized (mUseCasesLock) {
-            useCaseMediatorLifecycleController = mLifecycleToUseCaseMediatorControllerMap.get(
-                    lifecycleOwner);
-            if (useCaseMediatorLifecycleController == null) {
-                useCaseMediatorLifecycleController = createUseCaseMediator(lifecycleOwner);
-                mediatorSetup.setup(useCaseMediatorLifecycleController.getUseCaseMediator());
-            }
-        }
-        return useCaseMediatorLifecycleController;
-    }
-
-    /**
-     * Creates a new {@link UseCaseMediatorLifecycleController} associated with the given {@link
-     * LifecycleOwner} and adds the mediator to the repository.
-     *
-     * <p>The {@link UseCaseMediatorLifecycleController} is set to be an observer of the {@link
-     * LifecycleOwner}.
-     *
-     * @param lifecycleOwner to associate with the mediator
-     * @return a new {@link UseCaseMediatorLifecycleController}
-     * @throws IllegalArgumentException if the {@link androidx.lifecycle.Lifecycle} of
-     *                                  lifecycleOwner is already
-     *                                  {@link androidx.lifecycle.Lifecycle.State.DESTROYED}.
-     */
-    private UseCaseMediatorLifecycleController createUseCaseMediator(
-            LifecycleOwner lifecycleOwner) {
-        if (lifecycleOwner.getLifecycle().getCurrentState() == State.DESTROYED) {
-            throw new IllegalArgumentException(
-                    "Trying to create use case mediator with destroyed lifecycle.");
-        }
-
-        // Need to add observer before creating UseCaseMediatorLifecycleController to make sure
-        // UseCaseMediators can be stopped before the latest active one is started.
-        lifecycleOwner.getLifecycle().addObserver(createLifecycleObserver());
-        UseCaseMediatorLifecycleController useCaseMediatorLifecycleController =
-                new UseCaseMediatorLifecycleController(lifecycleOwner.getLifecycle());
-        synchronized (mUseCasesLock) {
-            mLifecycleToUseCaseMediatorControllerMap.put(lifecycleOwner,
-                    useCaseMediatorLifecycleController);
-        }
-        return useCaseMediatorLifecycleController;
-    }
-
-    /**
-     * Creates a {@link LifecycleObserver} to monitor state change of {@link LifecycleOwner}.
-     *
-     * @return a new {@link LifecycleObserver}
-     */
-    private LifecycleObserver createLifecycleObserver() {
-        return new LifecycleObserver() {
-            /**
-             * Monitors which {@link LifecycleOwner} receives an ON_START event and then stop
-             * others {@link UseCaseMediator} to keep only one active at a time.
-             */
-            @OnLifecycleEvent(Lifecycle.Event.ON_START)
-            public void onStart(LifecycleOwner lifecycleOwner) {
-                synchronized (mUseCasesLock) {
-                    // Only keep the last {@link LifecycleOwner} active. Stop the others.
-                    for (Map.Entry<LifecycleOwner, UseCaseMediatorLifecycleController> entry :
-                            mLifecycleToUseCaseMediatorControllerMap.entrySet()) {
-                        if (entry.getKey() != lifecycleOwner) {
-                            UseCaseMediator useCaseMediator = entry.getValue().getUseCaseMediator();
-                            if (useCaseMediator.isActive()) {
-                                useCaseMediator.stop();
-                            }
-                        }
-                    }
-
-                    mCurrentActiveLifecycleOwner = lifecycleOwner;
-                    mActiveLifecycleOwnerList.add(0, mCurrentActiveLifecycleOwner);
-                }
-            }
-
-            /**
-             * Monitors which {@link LifecycleOwner} receives an ON_STOP event.
-             */
-            @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
-            public void onStop(LifecycleOwner lifecycleOwner) {
-                synchronized (mUseCasesLock) {
-                    // Removes stopped lifecycleOwner from active list.
-                    mActiveLifecycleOwnerList.remove(lifecycleOwner);
-                    if (mCurrentActiveLifecycleOwner == lifecycleOwner) {
-                        // If stopped lifecycleOwner is original active one, check whether there
-                        // is other active lifecycleOwner and start UseCaseMediator belong to it.
-                        if (mActiveLifecycleOwnerList.size() > 0) {
-                            mCurrentActiveLifecycleOwner = mActiveLifecycleOwnerList.get(0);
-                            mLifecycleToUseCaseMediatorControllerMap.get(
-                                    mCurrentActiveLifecycleOwner).getUseCaseMediator().start();
-                        } else {
-                            mCurrentActiveLifecycleOwner = null;
-                        }
-                    }
-                }
-            }
-
-            /**
-             * Monitors which {@link LifecycleOwner} receives an ON_DESTROY event and then
-             * removes any {@link UseCaseMediatorLifecycleController} associated with it from this
-             * repository when that lifecycle is destroyed.
-             */
-            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
-            public void onDestroy(LifecycleOwner lifecycleOwner) {
-                synchronized (mUseCasesLock) {
-                    mLifecycleToUseCaseMediatorControllerMap.remove(lifecycleOwner);
-                }
-                lifecycleOwner.getLifecycle().removeObserver(this);
-            }
-        };
-    }
-
-    Collection<UseCaseMediatorLifecycleController> getUseCaseMediators() {
-        synchronized (mUseCasesLock) {
-            return Collections.unmodifiableCollection(
-                    mLifecycleToUseCaseMediatorControllerMap.values());
-        }
-    }
-
-    @VisibleForTesting
-    Map<LifecycleOwner, UseCaseMediatorLifecycleController> getUseCasesMap() {
-        synchronized (mUseCasesLock) {
-            return mLifecycleToUseCaseMediatorControllerMap;
-        }
-    }
-
-    /**
-     * The interface for doing additional setup work on a newly created {@link UseCaseMediator}
-     * instance.
-     */
-    public interface UseCaseMediatorSetup {
-        void setup(@NonNull UseCaseMediator useCaseMediator);
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
index 25ccb0d..eb1bfe7 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
@@ -23,7 +23,6 @@
 import androidx.annotation.NonNull;
 import androidx.camera.core.CameraUnavailableException;
 import androidx.camera.core.InitializationException;
-import androidx.camera.core.UseCase;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
@@ -40,11 +39,9 @@
 /**
  * A collection of {@link CameraInternal} instances.
  */
-public final class CameraRepository implements UseCaseMediator.StateChangeCallback {
+public final class CameraRepository {
     private static final String TAG = "CameraRepository";
-
     private final Object mCamerasLock = new Object();
-
     @GuardedBy("mCamerasLock")
     private final Map<String, CameraInternal> mCameras = new LinkedHashMap<>();
     @GuardedBy("mCamerasLock")
@@ -53,7 +50,6 @@
     private ListenableFuture<Void> mDeinitFuture;
     @GuardedBy("mCamerasLock")
     private CallbackToFutureAdapter.Completer<Void> mDeinitCompleter;
-
     /**
      * Initializes the repository from a {@link Context}.
      *
@@ -72,7 +68,6 @@
             }
         }
     }
-
     /**
      * Clear and release all cameras from the repository.
      */
@@ -85,7 +80,6 @@
             if (mCameras.isEmpty()) {
                 return mDeinitFuture == null ? Futures.immediateFuture(null) : mDeinitFuture;
             }
-
             ListenableFuture<Void> currentFuture = mDeinitFuture;
             if (currentFuture == null) {
                 // Create a single future that will be used to track closing of all cameras.
@@ -101,7 +95,6 @@
                 });
                 mDeinitFuture = currentFuture;
             }
-
             // Ensure all of the cameras have been added here before we start releasing so that
             // if the first camera release finishes inline it won't complete the future prematurely.
             mReleasingCameras.addAll(mCameras.values());
@@ -126,15 +119,12 @@
                     }
                 }, CameraXExecutors.directExecutor());
             }
-
             // Ensure all cameras are removed from the active "mCameras" map. This map can be
             // repopulated by #init().
             mCameras.clear();
-
             return currentFuture;
         }
     }
-
     /**
      * Gets a {@link CameraInternal} for the given id.
      *
@@ -146,15 +136,12 @@
     public CameraInternal getCamera(@NonNull String cameraId) {
         synchronized (mCamerasLock) {
             CameraInternal cameraInternal = mCameras.get(cameraId);
-
             if (cameraInternal == null) {
                 throw new IllegalArgumentException("Invalid camera: " + cameraId);
             }
-
             return cameraInternal;
         }
     }
-
     /**
      * Gets the set of all cameras.
      *
@@ -166,7 +153,6 @@
             return new LinkedHashSet<>(mCameras.values());
         }
     }
-
     /**
      * Gets the set of all camera ids.
      *
@@ -178,53 +164,4 @@
             return new LinkedHashSet<>(mCameras.keySet());
         }
     }
-
-    /**
-     * Attaches all the use cases in the {@link UseCaseMediator} and opens all the associated
-     * cameras.
-     *
-     * <p>This will start streaming data to the uses cases which are also online.
-     */
-    @Override
-    public void onActive(@NonNull UseCaseMediator useCaseMediator) {
-        synchronized (mCamerasLock) {
-            Map<String, Set<UseCase>> cameraIdToUseCaseMap =
-                    useCaseMediator.getCameraIdToUseCaseMap();
-            for (Map.Entry<String, Set<UseCase>> cameraUseCaseEntry :
-                    cameraIdToUseCaseMap.entrySet()) {
-                CameraInternal cameraInternal = getCamera(cameraUseCaseEntry.getKey());
-                attachUseCasesToCamera(cameraInternal, cameraUseCaseEntry.getValue());
-            }
-        }
-    }
-
-    /** Attaches a set of use cases to a camera. */
-    @GuardedBy("mCamerasLock")
-    private void attachUseCasesToCamera(CameraInternal cameraInternal, Set<UseCase> useCases) {
-        cameraInternal.attachUseCases(useCases);
-    }
-
-    /**
-     * Detaches all the use cases in the {@link UseCaseMediator} and closes the camera with no
-     * attached
-     * use cases.
-     */
-    @Override
-    public void onInactive(@NonNull UseCaseMediator useCaseMediator) {
-        synchronized (mCamerasLock) {
-            Map<String, Set<UseCase>> cameraIdToUseCaseMap =
-                    useCaseMediator.getCameraIdToUseCaseMap();
-            for (Map.Entry<String, Set<UseCase>> cameraUseCaseEntry :
-                    cameraIdToUseCaseMap.entrySet()) {
-                CameraInternal cameraInternal = getCamera(cameraUseCaseEntry.getKey());
-                detachUseCasesFromCamera(cameraInternal, cameraUseCaseEntry.getValue());
-            }
-        }
-    }
-
-    /** Detaches a set of use cases from a camera. */
-    @GuardedBy("mCamerasLock")
-    private void detachUseCasesFromCamera(CameraInternal cameraInternal, Set<UseCase> useCases) {
-        cameraInternal.detachUseCases(useCases);
-    }
 }
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
deleted file mode 100644
index 4703e74..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core.impl;
-
-import android.util.Log;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.camera.core.UseCase;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A collection of {@link UseCase}.
- *
- * <p>The set of {@link UseCase} instances have synchronized interactions with the {@link
- * CameraInternal}.
- */
-
-public final class UseCaseMediator {
-    private static final String TAG = "UseCaseMediator";
-
-    /**
-     * The lock for the single {@link StateChangeCallback} held by the mediator.
-     *
-     * <p>This lock is always acquired prior to acquiring the mUseCasesLock so that there is no
-     * lock-ordering deadlock.
-     */
-    private final Object mListenerLock = new Object();
-    /**
-     * The lock for accessing the map of use case types to use case instances.
-     *
-     * <p>This lock is always acquired after acquiring the mListenerLock so that there is no
-     * lock-ordering deadlock.
-     */
-    private final Object mUseCasesLock = new Object();
-    @GuardedBy("mUseCasesLock")
-    private final Set<UseCase> mUseCases = new HashSet<>();
-    @GuardedBy("mListenerLock")
-    private StateChangeCallback mStateChangeCallback;
-    private volatile boolean mIsActive = false;
-
-    /** Starts all the use cases so that they are brought into an online state. */
-    public void start() {
-        synchronized (mListenerLock) {
-            if (mStateChangeCallback != null) {
-                mStateChangeCallback.onActive(this);
-            }
-            mIsActive = true;
-        }
-    }
-
-    /** Stops all the use cases so that they are brought into an offline state. */
-    public void stop() {
-        synchronized (mListenerLock) {
-            if (mStateChangeCallback != null) {
-                mStateChangeCallback.onInactive(this);
-            }
-            mIsActive = false;
-        }
-    }
-
-    /** Sets the StateChangeCallback listener */
-    public void setListener(@NonNull StateChangeCallback stateChangeCallback) {
-        synchronized (mListenerLock) {
-            this.mStateChangeCallback = stateChangeCallback;
-        }
-    }
-
-    /**
-     * Adds the {@link UseCase} to the mediator.
-     *
-     * @return true if the use case is added, or false if the use case already exists in the
-     * mediator.
-     */
-    public boolean addUseCase(@NonNull UseCase useCase) {
-        synchronized (mUseCasesLock) {
-            return mUseCases.add(useCase);
-        }
-    }
-
-    /** Returns true if the {@link UseCase} is contained in the mediator. */
-    public boolean contains(@NonNull UseCase useCase) {
-        synchronized (mUseCasesLock) {
-            return mUseCases.contains(useCase);
-        }
-    }
-
-    /**
-     * Removes the {@link UseCase} from the mediator.
-     *
-     * @return Returns true if the use case is removed. Otherwise returns false (if the use case did
-     * not exist in the mediator).
-     */
-    public boolean removeUseCase(@NonNull UseCase useCase) {
-        synchronized (mUseCasesLock) {
-            return mUseCases.remove(useCase);
-        }
-    }
-
-    /**
-     * Called when lifecycle ends. Destroys all use cases in this mediator.
-     */
-    public void destroy() {
-        List<UseCase> useCasesToClear = new ArrayList<>();
-        synchronized (mUseCasesLock) {
-            useCasesToClear.addAll(mUseCases);
-            mUseCases.clear();
-        }
-
-        for (UseCase useCase : useCasesToClear) {
-            Log.d(TAG, "Destroying use case: " + useCase.getName());
-            useCase.onDetach(useCase.getCamera());
-            useCase.onDestroy();
-        }
-    }
-
-    /**
-     * Returns the collection of all the use cases currently contained by
-     * the{@link UseCaseMediator}.
-     */
-    @NonNull
-    public Collection<UseCase> getUseCases() {
-        synchronized (mUseCasesLock) {
-            return Collections.unmodifiableCollection(mUseCases);
-        }
-    }
-
-    /** Returns the map of all the use cases to its attached camera id. */
-    @NonNull
-    public Map<String, Set<UseCase>> getCameraIdToUseCaseMap() {
-        Map<String, Set<UseCase>> cameraIdToUseCases = new HashMap<>();
-        synchronized (mUseCasesLock) {
-            for (UseCase useCase : mUseCases) {
-                CameraInternal attachedCamera = useCase.getCamera();
-                if (attachedCamera != null) {
-                    String cameraId = attachedCamera.getCameraInfoInternal().getCameraId();
-                    Set<UseCase> useCaseSet = cameraIdToUseCases.get(cameraId);
-                    if (useCaseSet == null) {
-                        useCaseSet = new HashSet<>();
-                    }
-                    useCaseSet.add(useCase);
-                    cameraIdToUseCases.put(cameraId, useCaseSet);
-                }
-            }
-        }
-        return Collections.unmodifiableMap(cameraIdToUseCases);
-    }
-
-    public boolean isActive() {
-        return mIsActive;
-    }
-
-    /**
-     * Listener called when a {@link UseCaseMediator} transitions between active/inactive states
-     * .
-     */
-    public interface StateChangeCallback {
-        /**
-         * Called when a {@link UseCaseMediator} becomes active.
-         *
-         * <p>When a {@link UseCaseMediator} is active then all the contained {@link UseCase} become
-         * online. This means that the {@link CameraInternal} should transition to a state as
-         * close as possible to producing, but prior to actually producing data for the use case.
-         */
-        void onActive(@NonNull UseCaseMediator useCaseMediator);
-
-        /**
-         * Called when a {@link UseCaseMediator} becomes inactive.
-         *
-         * <p>When a {@link UseCaseMediator} is active then all the contained {@link UseCase} become
-         * offline.
-         */
-        void onInactive(@NonNull UseCaseMediator useCaseMediator);
-    }
-}
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
index ae1a46b..30ae34b 100644
--- 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
@@ -32,26 +32,36 @@
 import androidx.camera.core.impl.CameraInternal;
 import androidx.camera.core.impl.SurfaceConfig;
 import androidx.camera.core.impl.UseCaseConfig;
+import androidx.core.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 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.
+ *
+ * <p> The CameraUseCaseAdapter wraps a set of CameraInternals which it can dynamically switch
+ * between based on different configurations that are required by the adapter. This is used by
+ * extensions in order to select the correct CameraInternal instance which has the required
+ * camera id.
  */
 public final class CameraUseCaseAdapter {
     private final CameraInternal mCameraInternal;
+    private final LinkedHashSet<CameraInternal> mCameraInternals;
     private final CameraDeviceSurfaceManager mCameraDeviceSurfaceManager;
 
     private static final String TAG = "CameraUseCaseAdapter";
 
+    private final CameraId mId;
+
     @GuardedBy("mLock")
-    private final List<UseCase> mAttachedUseCases = new ArrayList<>();
+    private final List<UseCase> mUseCases = new ArrayList<>();
 
     @GuardedBy("mLock")
     @Nullable
@@ -59,20 +69,52 @@
 
     private final Object mLock = new Object();
 
+    // This indicates whether or not the UseCases that have been added to this adapter has
+    // actually been attached to the CameraInternal instance.
+    @GuardedBy("mLock")
+    private boolean mAttached = true;
+
     /**
      * Create a new {@link CameraUseCaseAdapter} instance.
      *
-     * @param cameraInternal the actual camera implementation that is wrapped
+     * @param cameraInternal             the actual camera implementation that is current attached
+     * @param cameras                    the set of cameras that are 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 LinkedHashSet<CameraInternal> cameras,
             @NonNull CameraDeviceSurfaceManager cameraDeviceSurfaceManager) {
         mCameraInternal = cameraInternal;
+        mCameraInternals = new LinkedHashSet<>(cameras);
+        mId = new CameraId(mCameraInternals);
         mCameraDeviceSurfaceManager = cameraDeviceSurfaceManager;
     }
 
     /**
+     * Generate a identifier for the set of {@link CameraInternal}.
+     */
+    @NonNull
+    public static CameraId generateCameraId(@NonNull LinkedHashSet<CameraInternal> cameras) {
+        return new CameraId(cameras);
+    }
+
+    /**
+     * Returns the identifier for this {@link CameraUseCaseAdapter}.
+     */
+    @NonNull
+    public CameraId getCameraId() {
+        return mId;
+    }
+
+    /**
+     * Returns true if the {@link CameraUseCaseAdapter} is an equivalent camera.
+     */
+    public boolean isEquivalent(@NonNull CameraUseCaseAdapter cameraUseCaseAdapter) {
+        return mId.equals(cameraUseCaseAdapter.getCameraId());
+    }
+
+    /**
      * Set the viewport that will be used for the {@link UseCase} attached to the camera.
      */
     public void setViewPort(@Nullable ViewPort viewPort) {
@@ -85,8 +127,6 @@
      * 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
@@ -104,19 +144,19 @@
     }
 
     /**
-     * Attach the specified collection of {@link UseCase} to the camera.
+     * Add the specified collection of {@link UseCase} to the adapter.
      *
-     * @throws CameraException Thrown if the combination of newly attached UseCases and the
-     * currently attached UseCases exceed the capability of the camera.
+     * @throws CameraException Thrown if the combination of newly added UseCases and the
+     *                         currently added UseCases exceed the capability of the camera.
      */
     @UseExperimental(markerClass = androidx.camera.core.ExperimentalUseCaseGroup.class)
-    public void attachUseCases(@NonNull Collection<UseCase> useCases) throws CameraException {
+    public void addUseCases(@NonNull Collection<UseCase> useCases) throws CameraException {
         synchronized (mLock) {
-            List<UseCase> useCaseListAfterUpdate = new ArrayList<>(mAttachedUseCases);
+            List<UseCase> useCaseListAfterUpdate = new ArrayList<>(mUseCases);
             List<UseCase> newUseCases = new ArrayList<>();
 
             for (UseCase useCase : useCases) {
-                if (mAttachedUseCases.contains(useCase)) {
+                if (mUseCases.contains(useCase)) {
                     Log.e(TAG, "Attempting to attach already attached UseCase");
                 } else {
                     useCaseListAfterUpdate.add(useCase);
@@ -133,8 +173,8 @@
             Map<UseCase, Size> suggestedResolutionsMap;
             try {
                 suggestedResolutionsMap =
-                        calculateSuggestedResolutions(newUseCases, mAttachedUseCases);
-            }  catch (IllegalArgumentException e) {
+                        calculateSuggestedResolutions(newUseCases, mUseCases);
+            } catch (IllegalArgumentException e) {
                 throw new CameraException(e.getMessage());
             }
 
@@ -157,23 +197,26 @@
             // Do all attaching related work
             for (UseCase useCase : newUseCases) {
                 useCase.onAttach(mCameraInternal);
-                useCase.updateSuggestedResolution(suggestedResolutionsMap.get(useCase));
+                useCase.updateSuggestedResolution(
+                        Preconditions.checkNotNull(suggestedResolutionsMap.get(useCase)));
             }
 
-            mAttachedUseCases.addAll(newUseCases);
-            mCameraInternal.attachUseCases(newUseCases);
+            mUseCases.addAll(newUseCases);
+            if (mAttached) {
+                mCameraInternal.attachUseCases(newUseCases);
+            }
         }
     }
 
     /**
-     * Detached the specified collection of {@link UseCase} from the camera.
+     * Remove the specified collection of {@link UseCase} from the adapter.
      */
-    public void detachUseCases(@NonNull Collection<UseCase> useCases) {
+    public void removeUseCases(@NonNull Collection<UseCase> useCases) {
         synchronized (mLock) {
             mCameraInternal.detachUseCases(useCases);
 
             for (UseCase useCase : useCases) {
-                if (mAttachedUseCases.contains(useCase)) {
+                if (mUseCases.contains(useCase)) {
                     useCase.onDetach(mCameraInternal);
                     useCase.onDestroy();
                 } else {
@@ -181,7 +224,49 @@
                 }
             }
 
-            mAttachedUseCases.removeAll(useCases);
+            mUseCases.removeAll(useCases);
+        }
+    }
+
+    /**
+     * Returns the UseCases currently associated with the adapter.
+     *
+     * <p> The UseCases may or may not be actually attached to the underlying
+     * {@link CameraInternal} instance.
+     */
+    @NonNull
+    public List<UseCase> getUseCases() {
+        synchronized (mLock) {
+            return mUseCases;
+        }
+    }
+
+    /**
+     * Attach the UseCases to the {@link CameraInternal} camera so that the UseCases can receive
+     * data if they are active.
+     *
+     * <p> This will start the underlying {@link CameraInternal} instance.
+     */
+    public void attachUseCases() {
+        synchronized (mLock) {
+            if (!mAttached) {
+                mCameraInternal.attachUseCases(mUseCases);
+                mAttached = true;
+            }
+        }
+    }
+
+    /**
+     * Detach the UseCases from the {@link CameraInternal} so that the UseCases stop receiving data.
+     *
+     * <p> This will stop the underlying {@link CameraInternal} instance.
+     */
+    public void detachUseCases() {
+        synchronized (mLock) {
+            if (mAttached) {
+                mCameraInternal.detachUseCases(mUseCases);
+                mAttached = false;
+            }
         }
     }
 
@@ -224,14 +309,6 @@
         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();
@@ -243,6 +320,36 @@
     }
 
     /**
+     * An identifier for a {@link CameraUseCaseAdapter}.
+     *
+     * <p>This identifies the actual camera instances that are wrapped by the
+     * CameraUseCaseAdapter and is used to determine if 2 different instances of
+     * CameraUseCaseAdapter are actually equivalent.
+     */
+    public static final class CameraId {
+        private final List<String> mIds;
+        CameraId(LinkedHashSet<CameraInternal> cameraInternals) {
+            mIds = new ArrayList<>();
+            for (CameraInternal cameraInternal : cameraInternals) {
+                mIds.add(cameraInternal.getCameraInfoInternal().getCameraId());
+            }
+        }
+
+        @Override
+        public boolean equals(Object cameraId) {
+            if (cameraId instanceof CameraId) {
+                return mIds.equals(((CameraId) cameraId).mIds);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return 53 * mIds.hashCode();
+        }
+    }
+
+    /**
      * An exception thrown when the {@link CameraUseCaseAdapter} errors in one of its operations.
      */
     public static final class CameraException extends Exception {
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java b/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
index b10f261..60de785 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
@@ -19,24 +19,16 @@
 
 import static org.mockito.Mockito.mock;
 
-import android.content.Context;
 import android.os.Build;
 
 import androidx.annotation.experimental.UseExperimental;
 import androidx.camera.core.impl.CameraControlInternal;
-import androidx.camera.core.impl.CameraDeviceSurfaceManager;
 import androidx.camera.core.impl.CameraInternal;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.impl.UseCaseConfigFactory;
 import androidx.camera.testing.fakes.FakeCamera;
-import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
 import androidx.camera.testing.fakes.FakeCameraFactory;
 import androidx.camera.testing.fakes.FakeCameraInfoInternal;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
-import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SmallTest;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -62,16 +54,6 @@
 
     @Before
     public void setUp() throws ExecutionException, InterruptedException {
-        Context context = ApplicationProvider.getApplicationContext();
-        CameraDeviceSurfaceManager.Provider surfaceManagerProvider =
-                ignored -> new FakeCameraDeviceSurfaceManager();
-        UseCaseConfigFactory.Provider configFactoryProvider = ignored -> {
-            ExtendableUseCaseConfigFactory defaultConfigFactory =
-                    new ExtendableUseCaseConfigFactory();
-            defaultConfigFactory.installDefaultProvider(FakeUseCaseConfig.class,
-                    cameraInfo -> new FakeUseCaseConfig.Builder().getUseCaseConfig());
-            return defaultConfigFactory;
-        };
         FakeCameraFactory cameraFactory = new FakeCameraFactory();
         mRearCamera = new FakeCamera(mock(CameraControlInternal.class),
                 new FakeCameraInfoInternal(REAR_ROTATION_DEGREE,
@@ -83,17 +65,6 @@
                         CameraSelector.LENS_FACING_FRONT));
         cameraFactory.insertCamera(CameraSelector.LENS_FACING_FRONT, FRONT_ID, () -> mFrontCamera);
         mCameras.add(mFrontCamera);
-        CameraXConfig.Builder appConfigBuilder =
-                new CameraXConfig.Builder()
-                        .setCameraFactoryProvider((ignored1, ignored2) -> cameraFactory)
-                        .setDeviceSurfaceManagerProvider(surfaceManagerProvider)
-                        .setUseCaseConfigFactoryProvider(configFactoryProvider);
-        CameraX.initialize(context, appConfigBuilder.build()).get();
-    }
-
-    @After
-    public void tearDown() throws ExecutionException, InterruptedException {
-        CameraX.shutdown().get();
     }
 
     @Test
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java b/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
index 8f218f4..701319c 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
@@ -111,7 +111,8 @@
     public void camerasAreReleasedByDeinit() throws ExecutionException, InterruptedException {
         List<CameraInternal> cameraInternals = new ArrayList<>();
         for (String cameraId : mCameraRepository.getCameraIds()) {
-            cameraInternals.add(mCameraRepository.getCamera(cameraId));
+            cameraInternals.add(
+                    mCameraRepository.getCamera(cameraId));
         }
 
         ListenableFuture<Void> deinitFuture = mCameraRepository.deinit();
diff --git a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
index d7c6615..01f99dc 100644
--- a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
+++ b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
@@ -19,6 +19,7 @@
 import androidx.camera.core.CameraSelector
 import androidx.annotation.experimental.UseExperimental
 import androidx.camera.core.CameraXConfig
+import androidx.camera.core.Preview
 import androidx.camera.testing.fakes.FakeAppConfig
 import androidx.camera.testing.fakes.FakeLifecycleOwner
 import androidx.concurrent.futures.await
@@ -37,7 +38,10 @@
 class ProcessCameraProviderTest {
 
     private val context = ApplicationProvider.getApplicationContext() as android.content.Context
-    private val lifecycleOwner = FakeLifecycleOwner()
+    private val lifecycleOwner0 = FakeLifecycleOwner()
+    private val lifecycleOwner1 = FakeLifecycleOwner()
+
+    private var provider: ProcessCameraProvider? = null
 
     @After
     fun tearDown() {
@@ -75,7 +79,7 @@
     fun configuredGetInstance_returnsProvider() {
         ProcessCameraProvider.configureInstance(FakeAppConfig.create())
         runBlocking {
-            val provider = ProcessCameraProvider.getInstance(context).await()
+            provider = ProcessCameraProvider.getInstance(context).await()
             assertThat(provider).isNotNull()
         }
     }
@@ -103,10 +107,120 @@
     fun canRetrieveCamera_withZeroUseCases() {
         ProcessCameraProvider.configureInstance(FakeAppConfig.create())
         runBlocking(MainScope().coroutineContext) {
-            val provider = ProcessCameraProvider.getInstance(context).await()
+            provider = ProcessCameraProvider.getInstance(context).await()
             val camera =
-                provider.bindToLifecycle(lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA)
+                provider!!.bindToLifecycle(lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA)
             assertThat(camera).isNotNull()
         }
     }
+
+    @Test
+    fun bindUseCase_isBound() {
+        ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+        runBlocking(MainScope().coroutineContext) {
+            provider = ProcessCameraProvider.getInstance(context).await()
+            val useCase = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+            provider!!.bindToLifecycle(
+                lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA,
+                useCase
+            )
+
+            assertThat(provider!!.isBound(useCase)).isTrue()
+        }
+    }
+
+    @Test
+    fun bindSecondUseCaseToDifferentLifecycle_firstUseCaseStillBound() {
+        ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+        runBlocking(MainScope().coroutineContext) {
+            provider = ProcessCameraProvider.getInstance(context).await()
+
+            val useCase0 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+            val useCase1 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+            provider!!.bindToLifecycle(
+                lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA,
+                useCase0
+            )
+            provider!!.bindToLifecycle(
+                lifecycleOwner1, CameraSelector.DEFAULT_BACK_CAMERA,
+                useCase1
+            )
+
+            // TODO(b/158595693) Add check on whether or not camera for fakeUseCase0 should be
+            //  exist or not
+            // assertThat(fakeUseCase0.camera).isNotNull() (or isNull()?)
+            assertThat(provider!!.isBound(useCase0)).isTrue()
+            assertThat(useCase1.camera).isNotNull()
+            assertThat(provider!!.isBound(useCase1)).isTrue()
+        }
+    }
+
+    @Test
+    fun isNotBound_afterUnbind() {
+        ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+        runBlocking(MainScope().coroutineContext) {
+            provider = ProcessCameraProvider.getInstance(context).await()
+
+            val useCase = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+            provider!!.bindToLifecycle(
+                lifecycleOwner0,
+                CameraSelector.DEFAULT_BACK_CAMERA,
+                useCase
+            )
+
+            provider!!.unbind(useCase)
+
+            assertThat(provider!!.isBound(useCase)).isFalse()
+        }
+    }
+
+    @Test
+    fun unbindFirstUseCase_secondUseCaseStillBound() {
+        ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+        runBlocking(MainScope().coroutineContext) {
+            provider = ProcessCameraProvider.getInstance(context).await()
+
+            val useCase0 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+            val useCase1 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+            provider!!.bindToLifecycle(
+                lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA,
+                useCase0, useCase1
+            )
+
+            provider!!.unbind(useCase0)
+
+            assertThat(useCase0.camera).isNull()
+            assertThat(provider!!.isBound(useCase0)).isFalse()
+            assertThat(useCase1.camera).isNotNull()
+            assertThat(provider!!.isBound(useCase1)).isTrue()
+        }
+    }
+
+    @Test
+    fun unbindAll_unbindsAllUseCasesFromCameras() {
+        ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+        runBlocking(MainScope().coroutineContext) {
+            provider = ProcessCameraProvider.getInstance(context).await()
+
+            val useCase = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+            provider!!.bindToLifecycle(
+                lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA, useCase
+            )
+
+            provider!!.unbindAll()
+
+            assertThat(useCase.camera).isNull()
+            assertThat(provider!!.isBound(useCase)).isFalse()
+        }
+    }
 }
\ No newline at end of file
diff --git a/camera/camera-testing/build.gradle b/camera/camera-testing/build.gradle
index ee9ec74..acdf19e 100644
--- a/camera/camera-testing/build.gradle
+++ b/camera/camera-testing/build.gradle
@@ -26,6 +26,7 @@
 
 dependencies {
     implementation("androidx.test:core:1.2.0")
+    implementation(ANDROIDX_TEST_RULES)
     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/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
index 8acc0b4..9544a65 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
@@ -16,7 +16,10 @@
 
 package androidx.camera.testing;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.Manifest;
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
@@ -39,9 +42,15 @@
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.util.Preconditions;
 import androidx.test.core.app.ApplicationProvider;
+import androidx.test.rule.GrantPermissionRule;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
@@ -58,6 +67,9 @@
     /** Amount of time to wait before timing out when trying to open a {@link CameraDevice}. */
     private static final int CAMERA_OPEN_TIMEOUT_SECONDS = 2;
 
+    /** The device debug property key for the tests to enable the camera pretest. */
+    private static final String PRETEST_CAMERA_TAG = "PreTestCamera";
+
     /**
      * Gets a new instance of a {@link CameraDevice}.
      *
@@ -444,4 +456,117 @@
                     "Unable to retrieve info for camera with id " + cameraId + ".", e);
         }
     }
+
+    /**
+     * Create a chained rule for the test cases that need to use the camera.
+     *
+     * <p>It will
+     * (1) Grant the camera permission.
+     * (2) Check if there is at least one camera on the device.
+     * (3) Test the camera can be opened successfully.
+     *
+     * <p>The method will set PreTestCamera throw exception will set when the PRETEST_CAMERA_TAG
+     * debug key for Log.isLoggable is enabled.
+     */
+    @NonNull
+    public static RuleChain grantCameraPermissionAndPreTest() {
+        return RuleChain.outerRule(GrantPermissionRule.grant(Manifest.permission.CAMERA)).around(
+                (base, description) -> new Statement() {
+                    @Override
+                    public void evaluate() throws Throwable {
+                        assumeTrue(deviceHasCamera());
+                        base.evaluate();
+                    }
+                }).around(
+                new CameraUtil.PreTestCamera(Log.isLoggable(PRETEST_CAMERA_TAG, Log.DEBUG)));
+    }
+
+    /**
+     * Pretest the camera device
+     *
+     * <p>Try to open the camera with the front and back lensFacing. It throws exception when
+     * camera is unavailable and mThrowOnError is true.
+     *
+     * <p>Passing false into the constructor {@link #PreTestCamera(boolean)}
+     * will never throw the exception when the camera is unavailable.
+     */
+    public static class PreTestCamera implements TestRule {
+        final boolean mThrowOnError;
+
+        public PreTestCamera(boolean throwOnError) {
+            mThrowOnError = throwOnError;
+        }
+
+        @NonNull
+        @Override
+        public Statement apply(@NonNull Statement base, @NonNull Description description) {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    boolean backStatus = true;
+                    if (hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK)) {
+                        Log.w(CameraUtil.class.getSimpleName(), "Fail to open the back camera");
+                        backStatus = tryOpenCamera(CameraSelector.LENS_FACING_BACK);
+                    }
+
+                    boolean frontStatus = true;
+                    if (hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+                        Log.w(CameraUtil.class.getSimpleName(), "Fail to open the front camera");
+                        frontStatus = tryOpenCamera(CameraSelector.LENS_FACING_FRONT);
+                    }
+                    boolean canOpenCamera = backStatus && frontStatus;
+
+                    if (canOpenCamera) {
+                        base.evaluate();
+                    } else {
+                        if (mThrowOnError) {
+                            throw new RuntimeException(
+                                    "CameraX_cannot_test_with_failed_camera, model:" + Build.MODEL);
+                        } else {
+                            // Ignore the test, so we only print a log without calling
+                            Log.w(CameraUtil.class.getSimpleName(),
+                                    "Camera fail, on test " + description.getDisplayName());
+                            base.evaluate();
+                        }
+                    }
+                }
+            };
+        }
+    }
+
+    /**
+     * Try to open the camera, and close it immediately.
+     *
+     * @param lensFacing the lensFacing of the camera to test
+     * @return true if the camera can be opened successfully
+     */
+    @SuppressLint("MissingPermission")
+    public static boolean tryOpenCamera(@CameraSelector.LensFacing int lensFacing) {
+        String cameraId = getCameraIdWithLensFacing(lensFacing);
+
+        if (cameraId == null) {
+            return false;
+        }
+
+        CameraDeviceHolder deviceHolder = null;
+        boolean ret = true;
+        try {
+            deviceHolder = new CameraDeviceHolder(getCameraManager(), cameraId);
+            if (deviceHolder.get() == null) {
+                ret = false;
+            }
+        } catch (Exception e) {
+            ret = false;
+        } finally {
+            if (deviceHolder != null) {
+                try {
+                    releaseCameraDevice(deviceHolder);
+                } catch (Exception e) {
+                    Log.e(CameraUtil.class.getSimpleName(), "Cannot close cameraDevice.", e);
+                }
+            }
+        }
+
+        return ret;
+    }
 }
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 0640d95..a03ce63 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
@@ -44,7 +44,9 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * A fake camera which will not produce any data, but provides a valid Camera implementation.
@@ -58,6 +60,7 @@
     private final CameraInfoInternal mCameraInfoInternal;
     private String mCameraId;
     private UseCaseAttachState mUseCaseAttachState;
+    private Set<UseCase> mAttachedUseCases = new HashSet<>();
     private State mState = State.CLOSED;
     private int mAvailableCameraCount = 1;
 
@@ -236,6 +239,8 @@
             return;
         }
 
+        mAttachedUseCases.addAll(useCases);
+
         Log.d(TAG, "Use cases " + useCases + " ATTACHED for camera " + mCameraId);
         for (UseCase useCase : useCases) {
             mUseCaseAttachState.setUseCaseAttached(useCase.getName() + useCase.hashCode(),
@@ -257,6 +262,8 @@
             return;
         }
 
+        mAttachedUseCases.removeAll(useCases);
+
         Log.d(TAG, "Use cases " + useCases + " DETACHED for camera " + mCameraId);
         for (UseCase useCase : useCases) {
             mUseCaseAttachState.setUseCaseDetached(useCase.getName() + useCase.hashCode());
@@ -271,6 +278,11 @@
         updateCaptureSessionConfig();
     }
 
+    @NonNull
+    public Set<UseCase> getAttachedUseCases() {
+        return mAttachedUseCases;
+    }
+
     // Returns fixed CameraControlInternal instance in order to verify the instance is correctly
     // attached.
     @NonNull
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java
index 665a5ee..b013a1f 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java
@@ -138,19 +138,18 @@
         final Bitmap scaled = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                 bitmap.getHeight(), scale, true);
 
-        // If fit* scale type, return scaled bitmap, since the whole preview is displayed, no
-        // cropping is needed.
         final PreviewView.ScaleType scaleType = mPreviewTransform.getScaleType();
-        if (scaleType == PreviewView.ScaleType.FIT_START
-                || scaleType == PreviewView.ScaleType.FIT_CENTER
-                || scaleType == PreviewView.ScaleType.FIT_END) {
-            return scaled;
-        }
 
-        // If fill* scale type, crop the scaled bitmap, then return it
         Preconditions.checkNotNull(mParent);
         int x = 0, y = 0;
         switch (scaleType) {
+            // If fit* scale type, return scaled bitmap, since the whole preview is displayed, no
+            // cropping is needed.
+            case FIT_START:
+            case FIT_CENTER:
+            case FIT_END:
+                return scaled;
+            // If fill* scale type, crop the scaled bitmap, then return it
             case FILL_START:
                 x = 0;
                 y = 0;
diff --git a/camera/integration-tests/coretestapp/build.gradle b/camera/integration-tests/coretestapp/build.gradle
index 7f6c5cd..af069b9 100644
--- a/camera/integration-tests/coretestapp/build.gradle
+++ b/camera/integration-tests/coretestapp/build.gradle
@@ -40,14 +40,6 @@
         }
     }
 
-    sourceSets {
-        main.manifest.srcFile 'src/main/AndroidManifest.xml'
-        main.java.srcDirs = ['src/main/java']
-        main.java.excludes = ['**/build/**']
-        main.java.includes = ['**/*.java']
-        main.res.srcDirs = ['src/main/res']
-    }
-
     buildTypes {
         debug {
             pseudoLocalesEnabled true
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXActivityTestExtensions.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXActivityTestExtensions.kt
new file mode 100644
index 0000000..3a465b5
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXActivityTestExtensions.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.integration.core
+
+import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.IdlingRegistry
+import androidx.test.espresso.assertion.ViewAssertions
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.testutils.withActivity
+
+/**
+ * Waits until the viewfinder has received frames and its idling resource has become idle.
+ */
+internal fun ActivityScenario<CameraXActivity>.waitForViewfinderIdle() {
+    val idlingResource = withActivity { viewIdlingResource }
+    try {
+        IdlingRegistry.getInstance().register(idlingResource)
+        // Check the activity launched and Preview displays frames.
+        Espresso.onView(ViewMatchers.withId(R.id.viewFinder))
+            .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+    } finally { // Always release the idling resource, in case of timeout exceptions.
+        IdlingRegistry.getInstance().unregister(idlingResource)
+    }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.java b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.java
deleted file mode 100644
index 0d69f3f..0000000
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.integration.core;
-
-import static androidx.camera.testing.CoreAppTestUtil.clearDeviceUI;
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.pm.ActivityInfo;
-
-import androidx.camera.core.CameraSelector;
-import androidx.camera.testing.CameraUtil;
-import androidx.camera.testing.CoreAppTestUtil;
-import androidx.lifecycle.Lifecycle;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.espresso.IdlingRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
-import androidx.test.uiautomator.UiDevice;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-// Test application lifecycle when using CameraX.
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public final class ExistingActivityLifecycleTest {
-    private static final int HOME_TIMEOUT_MS = 3000;
-
-    private final UiDevice mDevice =
-            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-    private final String mLauncherPackageName = mDevice.getLauncherPackageName();
-
-    @Rule
-    public GrantPermissionRule mCameraPermissionRule =
-            GrantPermissionRule.grant(android.Manifest.permission.CAMERA);
-    @Rule
-    public GrantPermissionRule mStoragePermissionRule =
-            GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
-    @Rule
-    public GrantPermissionRule mAudioPermissionRule =
-            GrantPermissionRule.grant(android.Manifest.permission.RECORD_AUDIO);
-
-    @Before
-    public void setup() {
-        assumeTrue(CameraUtil.deviceHasCamera());
-        CoreAppTestUtil.assumeCompatibleDevice();
-        assertThat(mLauncherPackageName, notNullValue());
-
-        // Clear the device UI before start each test.
-        clearDeviceUI(InstrumentationRegistry.getInstrumentation());
-    }
-
-    @After
-    public void tearDown() {
-        mDevice.pressHome();
-        mDevice.waitForIdle(HOME_TIMEOUT_MS);
-    }
-
-    // Check if Preview screen is updated or not, after Destroy-Create lifecycle.
-    @Test
-    public void checkPreviewUpdatedAfterDestroyRecreate() {
-        // Launch activity.
-        try (ActivityScenario<CameraXActivity> activityScenario =
-                     ActivityScenario.launch(CameraXActivity.class)) {
-            // Check for view idle, then destroy it.
-            checkForViewIdle(activityScenario);
-            // Launch new activity and check for view idle.
-            checkForViewIdle(activityScenario.recreate());
-        }
-    }
-
-    // Check if Preview screen is updated or not, after Stop-Resume lifecycle.
-    @Test
-    public void checkPreviewUpdatedAfterStopResume() {
-        // Launch activity.
-        try (ActivityScenario<CameraXActivity> activityScenario =
-                     ActivityScenario.launch(CameraXActivity.class)) {
-            // Check view gets to idle.
-            checkForViewIdle(activityScenario);
-            // Go through pause/resume then check again for view to get frames then idle.
-            activityScenario.moveToState(Lifecycle.State.CREATED).onActivity(activity -> {
-                activity.resetViewIdlingResource();
-            });
-            checkForViewIdle(activityScenario.moveToState(Lifecycle.State.RESUMED));
-
-            // Go through pause/resume then check again for view to get frames then idle, the
-            // second pass is used to protect against previous observed issues.
-            activityScenario.moveToState(Lifecycle.State.CREATED).onActivity(activity -> {
-                activity.resetViewIdlingResource();
-            });
-            checkForViewIdle(activityScenario.moveToState(Lifecycle.State.RESUMED));
-        }
-    }
-
-    // Check if Preview screen is updated or not, after toggling camera, then a Destroy-Create
-    // lifecycle.
-    @Test
-    public void checkPreviewUpdatedAfterToggleCameraAndStopResume() {
-        // check have front camera
-        assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
-        try (ActivityScenario<CameraXActivity> activityScenario =
-                     ActivityScenario.launch(CameraXActivity.class)) {
-            try {
-                activityScenario.onActivity(activity -> {
-                    IdlingRegistry.getInstance().register(activity.getViewIdlingResource());
-                });
-                onView(withId(R.id.viewFinder)).check(matches(isDisplayed()));
-                // Switch camera.
-                onView(withId(R.id.direction_toggle)).perform(click());
-                // Go through pause/resume then check again for view to get frames then idle.
-                activityScenario.moveToState(Lifecycle.State.CREATED);
-                activityScenario.onActivity(activity -> {
-                    activity.resetViewIdlingResource();
-                });
-                activityScenario.moveToState(Lifecycle.State.RESUMED);
-                onView(withId(R.id.viewFinder)).check(matches(isDisplayed()));
-            } finally {
-                activityScenario.onActivity(activity -> {
-                    IdlingRegistry.getInstance().unregister(activity.getViewIdlingResource());
-                });
-            }
-        }
-    }
-
-    // Check if Preview screen is updated or not, after rotate device, and Stop-Resume lifecycle.
-    @Test
-    public void checkPreviewUpdatedAfterRotateDeviceAndStopResume() {
-        // Launch activity.
-        try (ActivityScenario<CameraXActivity> activityScenario =
-                checkForViewIdle(ActivityScenario.launch(CameraXActivity.class))) {
-            // Check view gets to idle.
-            checkForViewIdle(activityScenario);
-            // Rotate to Landscape and the activity will be recreated.
-            activityScenario.onActivity(activity -> {
-                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-            });
-            // Get idling from the re-created activity.
-            activityScenario.onActivity(activity -> {
-                activity.resetViewIdlingResource();
-            });
-            checkForViewIdle(activityScenario);
-
-            activityScenario.moveToState(Lifecycle.State.CREATED);
-            activityScenario.onActivity(activity -> {
-                activity.resetViewIdlingResource();
-            });
-            activityScenario.moveToState(Lifecycle.State.RESUMED);
-
-            checkForViewIdle(activityScenario);
-        }
-    }
-
-    private ActivityScenario<CameraXActivity>
-            checkForViewIdle(ActivityScenario<CameraXActivity> activityScenario) {
-        try {
-            activityScenario.onActivity(activity -> {
-                IdlingRegistry.getInstance().register(activity.getViewIdlingResource());
-            });
-            // Check the activity launched and Preview displays frames.
-            onView(withId(R.id.viewFinder)).check(matches(isDisplayed()));
-        } finally {
-            // Always release the idling resource, in case of timeout exceptions.
-            activityScenario.onActivity(activity -> {
-                IdlingRegistry.getInstance().unregister(activity.getViewIdlingResource());
-            });
-        }
-        return activityScenario;
-    }
-}
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.kt
new file mode 100644
index 0000000..857a8ee
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.camera.integration.core
+
+import android.Manifest
+import android.app.Instrumentation
+import androidx.camera.core.CameraSelector
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CoreAppTestUtil
+import androidx.lifecycle.Lifecycle.State.CREATED
+import androidx.lifecycle.Lifecycle.State.RESUMED
+import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.GrantPermissionRule
+import androidx.test.uiautomator.UiDevice
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val HOME_TIMEOUT_MS = 3000L
+private const val ROTATE_TIMEOUT_MS = 2000L
+
+// Test application lifecycle when using CameraX.
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class ExistingActivityLifecycleTest {
+    private val mDevice =
+        UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+    private val mLauncherPackageName = mDevice.launcherPackageName
+
+    @get:Rule
+    val mPermissionRule: GrantPermissionRule =
+        GrantPermissionRule.grant(
+            Manifest.permission.CAMERA,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE,
+            Manifest.permission.RECORD_AUDIO
+        )
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(CameraUtil.deviceHasCamera())
+        CoreAppTestUtil.assumeCompatibleDevice()
+        assertThat(mLauncherPackageName).isNotNull()
+        // Clear the device UI before start each test.
+        CoreAppTestUtil.clearDeviceUI(InstrumentationRegistry.getInstrumentation())
+        // Use the natural orientation throughout these tests to ensure the activity isn't
+        // recreated unexpectedly. This will also freeze the sensors until
+        // mDevice.unfreezeRotation() in the tearDown() method. Any simulated rotations will be
+        // explicitly initiated from within the test.
+        mDevice.setOrientationNatural()
+    }
+
+    @After
+    fun tearDown() {
+        // Unfreeze rotation so the device can choose the orientation via its own policy. Be nice
+        // to other tests :)
+        mDevice.unfreezeRotation()
+        mDevice.pressHome()
+        mDevice.waitForIdle(HOME_TIMEOUT_MS)
+    }
+
+    // Check if Preview screen is updated or not, after Destroy-Create lifecycle.
+    @Test
+    fun checkPreviewUpdatedAfterDestroyRecreate() {
+        with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+            use { // Ensure ActivityScenario is cleaned up properly
+                // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+                waitForViewfinderIdle()
+                // Destroy previous activity, launch new activity and check for view idle.
+                recreate()
+                waitForViewfinderIdle()
+            }
+        }
+    }
+
+    // Check if Preview screen is updated or not, after Stop-Resume lifecycle.
+    @Test
+    fun checkPreviewUpdatedAfterStopResume() {
+        with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+            use { // Ensure ActivityScenario is cleaned up properly
+                // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+                waitForViewfinderIdle()
+                // Go through pause/resume then check again for view to get frames then idle.
+                moveToState(CREATED)
+
+                withActivity { resetViewIdlingResource() }
+
+                moveToState(RESUMED)
+
+                waitForViewfinderIdle()
+                // Go through pause/resume then check again for view to get frames then idle,
+                // the second pass is used to protect against previous observed issues.
+                moveToState(CREATED)
+
+                withActivity { resetViewIdlingResource() }
+
+                moveToState(RESUMED)
+
+                waitForViewfinderIdle()
+            }
+        }
+    }
+
+    // Check if Preview screen is updated or not, after toggling camera,
+    // then a Destroy-Create lifecycle.
+    @Test
+    fun checkPreviewUpdatedAfterToggleCameraAndStopResume() = runBlocking {
+        // check have front camera
+        Assume.assumeTrue(
+            CameraUtil.hasCameraWithLensFacing(
+                CameraSelector.LENS_FACING_FRONT
+            )
+        )
+
+        with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+            use { // Ensure ActivityScenario is cleaned up properly
+                // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+                waitForViewfinderIdle()
+
+                // Switch camera.
+                Espresso.onView(ViewMatchers.withId(R.id.direction_toggle))
+                    .perform(ViewActions.click())
+
+                // TODO(b/159257773): Currently have no reliable way of checking that camera has
+                //  switched. Delay to ensure previous camera has stopped streaming and the
+                //  idling resource actually is becoming idle due to frames from front camera.
+                delay(500)
+
+                // Check front camera is now idle
+                withActivity { resetViewIdlingResource() }
+                waitForViewfinderIdle()
+
+                // Go through pause/resume then check again for view to get frames then idle.
+                moveToState(CREATED)
+                withActivity { resetViewIdlingResource() }
+                moveToState(RESUMED)
+                waitForViewfinderIdle()
+            }
+        }
+    }
+
+    // Check if Preview screen is updated or not, after rotate device, and Stop-Resume lifecycle.
+    @Test
+    fun checkPreviewUpdatedAfterRotateDeviceAndStopResume() {
+        with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+            use { // Ensure ActivityScenario is cleaned up properly
+                // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+                waitForViewfinderIdle()
+
+                // Rotate to the orientation left of natural and wait for the activity to be
+                // recreated.
+                rotateDeviceLeftAndWait()
+
+                // Get idling from the re-created activity.
+                withActivity { resetViewIdlingResource() }
+                waitForViewfinderIdle()
+
+                moveToState(CREATED)
+                withActivity { resetViewIdlingResource() }
+                moveToState(RESUMED)
+                waitForViewfinderIdle()
+            }
+        }
+    }
+
+    private fun rotateDeviceLeftAndWait() {
+        // Create an ActivityMonitor to explicitly wait for the activity to be recreated after
+        // rotating the device.
+        val monitor =
+            Instrumentation.ActivityMonitor(CameraXActivity::class.java.name, null, false)
+        InstrumentationRegistry.getInstrumentation().addMonitor(monitor)
+        mDevice.setOrientationLeft()
+        // Wait for the rotation to complete
+        InstrumentationRegistry.getInstrumentation().waitForMonitorWithTimeout(
+            monitor,
+            ROTATE_TIMEOUT_MS
+        )
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+    }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt
index e026c9a..c5660a5 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.camera.integration.uiwidgets.rotations.imageanalysis
 
-import android.Manifest
 import android.content.Context
 import android.content.Intent
 import androidx.camera.camera2.Camera2Config
@@ -79,7 +78,7 @@
 
     @get:Rule
     val mCameraPermissionRule: GrantPermissionRule =
-        GrantPermissionRule.grant(Manifest.permission.CAMERA)
+        GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
 
     @Before
     fun setUp() {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt
index 4549155..debff6e 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.camera.integration.uiwidgets.rotations.imageanalysis
 
-import android.Manifest
 import android.content.Context
 import android.content.Intent
 import android.view.Surface
@@ -82,7 +81,7 @@
 
     @get:Rule
     val mCameraPermissionRule: GrantPermissionRule =
-        GrantPermissionRule.grant(Manifest.permission.CAMERA)
+        GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
 
     @Before
     fun setUp() {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt
index eccd02e..0bc425e 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt
@@ -16,7 +16,6 @@
 
 package androidx.camera.integration.uiwidgets.rotations.imageanalysis
 
-import android.Manifest
 import android.content.Context
 import android.content.Intent
 import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
@@ -91,7 +90,7 @@
 
     @get:Rule
     val mCameraPermissionRule: GrantPermissionRule =
-        GrantPermissionRule.grant(Manifest.permission.CAMERA)
+        GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
 
     @Before
     fun setUp() {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/ImageCaptureTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/ImageCaptureTest.kt
new file mode 100644
index 0000000..7bdca52
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/ImageCaptureTest.kt
@@ -0,0 +1,157 @@
+/*
+ * 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.uiwidgets.rotations.imagecapture
+
+import android.content.Intent
+import android.os.Build
+import android.view.View
+import androidx.camera.core.CameraSelector
+import androidx.camera.integration.uiwidgets.R
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CoreAppTestUtil
+import androidx.test.core.app.ActivityScenario
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import java.util.concurrent.TimeUnit
+
+/**
+ * Base class for rotation image capture tests.
+ *
+ * The flow of the tests is:
+ * - Launch the activity
+ * - Wait fo the camera to be set up
+ * - Rotate
+ * - Wait a couple of frames
+ * - Take a picture
+ * - Wait for the image capture callback
+ * - Verify the picture's rotation or resolution
+ */
+abstract class ImageCaptureTest<A : CameraActivity> {
+
+    protected fun setUp(lensFacing: Int) {
+        // TODO(b/147448711) Cuttlefish seems to have an issue handling rotation. Might be
+        //  related to the attached bug.
+        assumeFalse(
+            "Cuttlefish does not correctly handle rotating. Unable to test.",
+            Build.MODEL.contains("Cuttlefish")
+        )
+
+        CoreAppTestUtil.assumeCompatibleDevice()
+        Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing))
+
+        // Clear the device's UI and ensure it's in a natural orientation
+        CoreAppTestUtil.clearDeviceUI(InstrumentationRegistry.getInstrumentation())
+        val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+        device.setOrientationNatural()
+    }
+
+    protected fun tearDown() {
+        val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+        device.unfreezeRotation()
+    }
+
+    protected inline fun <reified A : CameraActivity> verifyRotation(
+        lensFacing: Int,
+        captureMode: Int,
+        rotate: ActivityScenario<A>.() -> Unit
+    ) {
+        val activityScenario: ActivityScenario<A> = launchActivity(lensFacing, captureMode)
+        activityScenario.use { scenario ->
+
+            // Wait until the camera is set up and analysis starts receiving frames
+            scenario.waitOnCameraFrames()
+
+            // Rotate
+            rotate(scenario)
+
+            // Wait a couple of frames after rotation
+            scenario.waitOnCameraFrames()
+
+            // Take picture
+            scenario.onActivity {
+                val view = it.findViewById<View>(R.id.previewView)
+                view.performClick()
+            }
+
+            // Wait until a picture is taken and the capture callback is invoked
+            val captureDone = scenario.withActivity { mCaptureDone }
+            assertThat(captureDone.tryAcquire(TIMEOUT, TimeUnit.SECONDS)).isTrue()
+
+            // If the camera HAL doesn't rotate the image, the captured image should contain a
+            // rotation that's equal to the sensor rotation relative to target rotation
+            val (sensorToTargetRotation, imageRotationDegrees) = scenario.withActivity {
+                Pair(
+                    getSensorRotationRelativeToCaptureTargetRotation(),
+                    mCaptureResult?.getRotation()
+                )
+            }
+            val areRotationsEqual = sensorToTargetRotation == imageRotationDegrees
+
+            // If the camera HAL did rotate the image, verifying the image's rotation isn't
+            // possible, so we make sure the image has the correct orientation/resolution.
+            val (expectedResolution, imageSize) = scenario.withActivity {
+                Pair(getCaptureResolution(), mCaptureResult?.getResolution())
+            }
+            val areResolutionsEqual = expectedResolution == imageSize
+
+            assertThat(areRotationsEqual || areResolutionsEqual).isTrue()
+
+            // Delete captured image
+            scenario.withActivity { mCaptureResult?.delete() ?: Unit }
+        }
+    }
+
+    protected inline fun <reified A : CameraActivity> launchActivity(
+        lensFacing: Int,
+        captureMode: Int
+    ): ActivityScenario<A> {
+        val intent = Intent(
+            ApplicationProvider.getApplicationContext(),
+            A::class.java
+        ).apply {
+            putExtra(CameraActivity.KEY_LENS_FACING, lensFacing)
+            putExtra(CameraActivity.KEY_IMAGE_CAPTURE_MODE, captureMode)
+        }
+        return ActivityScenario.launch<A>(intent)
+    }
+
+    protected inline fun <reified A : CameraActivity> ActivityScenario<A>.waitOnCameraFrames() {
+        val analysisRunning = withActivity { mAnalysisRunning }
+        assertThat(analysisRunning.tryAcquire(IMAGES_COUNT, TIMEOUT, TimeUnit.SECONDS)).isTrue()
+    }
+
+    companion object {
+        protected const val IMAGES_COUNT = 30
+        protected const val TIMEOUT = 5L
+        @JvmStatic
+        protected val captureModes = arrayOf(
+            CameraActivity.IMAGE_CAPTURE_MODE_IN_MEMORY,
+            CameraActivity.IMAGE_CAPTURE_MODE_FILE,
+            CameraActivity.IMAGE_CAPTURE_MODE_OUTPUT_STREAM,
+            CameraActivity.IMAGE_CAPTURE_MODE_MEDIA_STORE
+        )
+        @JvmStatic
+        protected val lensFacing =
+            arrayOf(CameraSelector.LENS_FACING_BACK, CameraSelector.LENS_FACING_FRONT)
+    }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/LockedOrientationTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/LockedOrientationTest.kt
new file mode 100644
index 0000000..47c13ec
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/LockedOrientationTest.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.camera.integration.uiwidgets.rotations.imagecapture
+
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.integration.uiwidgets.rotations.LockedOrientationActivity
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.rule.GrantPermissionRule
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@LargeTest
+class LockedOrientationTest(
+    private val lensFacing: Int,
+    private val rotationDegrees: Int,
+    private val captureMode: Int
+) : ImageCaptureTest<LockedOrientationActivity>() {
+
+    companion object {
+        private val rotationDegrees = arrayOf(0, 90, 180, 270)
+        @JvmStatic
+        @Parameterized.Parameters(name = "lensFacing={0}, rotationDegrees={1}, captureMode={2}")
+        fun data() = mutableListOf<Array<Any?>>().apply {
+            lensFacing.forEach { lens ->
+                rotationDegrees.forEach { rotation ->
+                    captureModes.forEach { mode ->
+                        add(arrayOf(lens, rotation, mode))
+                    }
+                }
+            }
+        }
+    }
+
+    @get:Rule
+    val mCameraPermissionRule: GrantPermissionRule =
+        GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
+
+    @Before
+    fun before() {
+        setUp(lensFacing)
+    }
+
+    @After
+    fun after() {
+        tearDown()
+    }
+
+    @Test
+    fun verifyRotation() {
+        verifyRotation<LockedOrientationActivity>(lensFacing, captureMode) {
+            rotate(rotationDegrees)
+        }
+    }
+
+    private fun ActivityScenario<LockedOrientationActivity>.rotate(rotationDegrees: Int) {
+        onActivity { activity ->
+            activity.mOrientationEventListener.onOrientationChanged(rotationDegrees)
+        }
+    }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/OrientationConfigChangesTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/OrientationConfigChangesTest.kt
new file mode 100644
index 0000000..a6a816b
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/OrientationConfigChangesTest.kt
@@ -0,0 +1,104 @@
+/*
+ * 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.uiwidgets.rotations.imagecapture
+
+import android.view.Surface
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.integration.uiwidgets.rotations.OrientationConfigChangesOverriddenActivity
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.GrantPermissionRule
+import androidx.testutils.withActivity
+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.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.TimeUnit
+
+@RunWith(Parameterized::class)
+@LargeTest
+class OrientationConfigChangesTest(
+    private val lensFacing: Int,
+    private val rotation: Int,
+    private val captureMode: Int
+) : ImageCaptureTest<OrientationConfigChangesOverriddenActivity>() {
+
+    companion object {
+        private val rotations = arrayOf(
+            Surface.ROTATION_0,
+            Surface.ROTATION_90,
+            Surface.ROTATION_180,
+            Surface.ROTATION_270
+        )
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "lensFacing={0}, rotation={1}, captureMode={2}")
+        fun data() = mutableListOf<Array<Any?>>().apply {
+            lensFacing.forEach { lens ->
+                rotations.forEach { rotation ->
+                    captureModes.forEach { mode ->
+                        add(arrayOf(lens, rotation, mode))
+                    }
+                }
+            }
+        }
+    }
+
+    @get:Rule
+    val mCameraPermissionRule: GrantPermissionRule =
+        GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
+
+    @Before
+    fun before() {
+        setUp(lensFacing)
+    }
+
+    @After
+    fun after() {
+        tearDown()
+    }
+
+    @Test
+    fun verifyRotation() {
+        verifyRotation<OrientationConfigChangesOverriddenActivity>(
+            lensFacing,
+            captureMode
+        ) {
+            if (rotate(rotation)) {
+
+                // Wait for the rotation to occur
+                waitForRotation()
+            }
+        }
+    }
+
+    private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.rotate(rotation: Int):
+            Boolean {
+        val currentRotation = withActivity { this.display!!.rotation }
+        InstrumentationRegistry.getInstrumentation().uiAutomation.setRotation(rotation)
+        return currentRotation != rotation
+    }
+
+    private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.waitForRotation() {
+        val displayChanged = withActivity { mDisplayChanged }
+        assertThat(displayChanged.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+    }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/UnlockedOrientationTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/UnlockedOrientationTest.kt
new file mode 100644
index 0000000..d6e9f0c
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/UnlockedOrientationTest.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.uiwidgets.rotations.imagecapture
+
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.integration.uiwidgets.rotations.UnlockedOrientationActivity
+import androidx.camera.integration.uiwidgets.rotations.UnlockedOrientationActivity.Companion.mCreated
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.rule.GrantPermissionRule
+import androidx.testutils.withActivity
+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.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.Semaphore
+import java.util.concurrent.TimeUnit
+
+@RunWith(Parameterized::class)
+@LargeTest
+class UnlockedOrientationTest(
+    private val lensFacing: Int,
+    private val orientation: Int,
+    private val captureMode: Int
+) : ImageCaptureTest<UnlockedOrientationActivity>() {
+
+    companion object {
+        val ORIENTATION_MAP = hashMapOf(
+            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT to Configuration.ORIENTATION_PORTRAIT,
+            ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT to Configuration.ORIENTATION_PORTRAIT,
+            ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE to Configuration.ORIENTATION_LANDSCAPE,
+            ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE to Configuration.ORIENTATION_LANDSCAPE
+        )
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "lensFacing={0}, orientation={1}, captureMode={2}")
+        fun data() = mutableListOf<Array<Any?>>().apply {
+            lensFacing.forEach { lens ->
+                ORIENTATION_MAP.keys.forEach { orientation ->
+                    captureModes.forEach { mode ->
+                        add(arrayOf(lens, orientation, mode))
+                    }
+                }
+            }
+        }
+    }
+
+    @get:Rule
+    val mCameraPermissionRule: GrantPermissionRule =
+        GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
+
+    @Before
+    fun before() {
+        setUp(lensFacing)
+    }
+
+    @After
+    fun after() {
+        tearDown()
+    }
+
+    @Test
+    fun verifyRotation() {
+        verifyRotation<UnlockedOrientationActivity>(lensFacing, captureMode) {
+            if (rotate(orientation)) {
+
+                // Wait for the rotation to occur
+                waitForRotation()
+            }
+        }
+    }
+
+    private fun ActivityScenario<UnlockedOrientationActivity>.rotate(orientation: Int): Boolean {
+        val currentOrientation = withActivity { resources.configuration.orientation }
+        val didRotate = ORIENTATION_MAP[orientation] != currentOrientation
+        mCreated = Semaphore(0)
+        onActivity { activity ->
+            activity.requestedOrientation = orientation
+        }
+        return didRotate
+    }
+
+    private fun waitForRotation() {
+        assertThat(mCreated.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+    }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml b/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml
index 3f58bb8..46c13d2 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml
@@ -39,5 +39,6 @@
     </application>
 
     <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
 </manifest>
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
index ac35c412..6e55523 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
@@ -23,6 +23,7 @@
 import android.os.Bundle
 import android.provider.MediaStore
 import android.util.Log
+import android.util.Size
 import androidx.annotation.VisibleForTesting
 import androidx.appcompat.app.AppCompatActivity
 import androidx.camera.core.Camera
@@ -32,7 +33,6 @@
 import androidx.camera.core.ImageCaptureException
 import androidx.camera.core.ImageProxy
 import androidx.camera.core.Preview
-import androidx.camera.core.impl.utils.Exif
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
 import androidx.camera.integration.uiwidgets.R
 import androidx.camera.lifecycle.ProcessCameraProvider
@@ -160,15 +160,15 @@
             CameraXExecutors.mainThreadExecutor(),
             object : ImageCapture.OnImageCapturedCallback() {
                 override fun onCaptureSuccess(image: ImageProxy) {
-                    mCapturedImageRotation = image.imageInfo.rotationDegrees
+                    mCaptureResult = ImageCaptureResult.InMemory(image)
                     mCaptureDone.release()
-                    Log.d(TAG, "InMemory captured image rotation = $mCapturedImageRotation")
                     image.close()
+                    Log.d(TAG, "MediaStore captured successful")
                 }
 
                 override fun onError(exception: ImageCaptureException) {
-                    Log.e(TAG, "InMemory capture failed", exception)
                     mCaptureDone.release()
+                    Log.e(TAG, "InMemory capture failed", exception)
                 }
             })
     }
@@ -181,14 +181,14 @@
             CameraXExecutors.mainThreadExecutor(),
             object : ImageCapture.OnImageSavedCallback {
                 override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
-                    mCapturedImageRotation = Exif.createFromFile(imageFile).rotation
+                    mCaptureResult = ImageCaptureResult.FileOrOutputStream(imageFile)
                     mCaptureDone.release()
-                    Log.d(TAG, "File captured image rotation = $mCapturedImageRotation")
+                    Log.d(TAG, "MediaStore captured successful")
                 }
 
                 override fun onError(exception: ImageCaptureException) {
-                    Log.e(TAG, "File capture failed", exception)
                     mCaptureDone.release()
+                    Log.e(TAG, "File capture failed", exception)
                 }
             })
     }
@@ -202,14 +202,14 @@
             CameraXExecutors.mainThreadExecutor(),
             object : ImageCapture.OnImageSavedCallback {
                 override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
-                    mCapturedImageRotation = Exif.createFromFile(imageFile).rotation
+                    mCaptureResult = ImageCaptureResult.FileOrOutputStream(imageFile)
                     mCaptureDone.release()
-                    Log.d(TAG, "OutputStream captured image rotation = $mCapturedImageRotation")
+                    Log.d(TAG, "MediaStore captured successful")
                 }
 
                 override fun onError(exception: ImageCaptureException) {
-                    Log.e(TAG, "OutputStream capture failed", exception)
                     mCaptureDone.release()
+                    Log.e(TAG, "OutputStream capture failed", exception)
                 }
             })
     }
@@ -227,15 +227,15 @@
             CameraXExecutors.mainThreadExecutor(),
             object : ImageCapture.OnImageSavedCallback {
                 override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
-                    val inputStream = contentResolver.openInputStream(outputFileResults.savedUri!!)
-                    mCapturedImageRotation = Exif.createFromInputStream(inputStream!!).rotation
+                    mCaptureResult =
+                        ImageCaptureResult.MediaStore(contentResolver, outputFileResults.savedUri!!)
                     mCaptureDone.release()
-                    Log.d(TAG, "MediaStore captured image rotation = $mCapturedImageRotation")
+                    Log.d(TAG, "MediaStore captured successful")
                 }
 
                 override fun onError(exception: ImageCaptureException) {
-                    Log.e(TAG, "MediaStore capture failed", exception)
                     mCaptureDone.release()
+                    Log.e(TAG, "MediaStore capture failed", exception)
                 }
             })
     }
@@ -259,14 +259,33 @@
     val mCaptureDone = Semaphore(0)
 
     @VisibleForTesting
-    var mCapturedImageRotation = -1
-    // Todo: Delete captured images when test finishes
+    var mCaptureResult: ImageCaptureResult? = null
 
     @VisibleForTesting
     fun getSensorRotationRelativeToAnalysisTargetRotation(): Int {
         val targetRotation = mImageAnalysis.targetRotation
         return mCamera.cameraInfo.getSensorRotationDegrees(targetRotation)
     }
+
+    @VisibleForTesting
+    fun getSensorRotationRelativeToCaptureTargetRotation(): Int {
+        val targetRotation = mImageCapture.targetRotation
+        return mCamera.cameraInfo.getSensorRotationDegrees(targetRotation)
+    }
+
+    @Suppress("RestrictedApi")
+    @VisibleForTesting
+    fun getCaptureResolution(): Size {
+        val resolution = mImageCapture.attachedSurfaceResolution
+            ?: throw IllegalStateException("ImageCapture surface resolution is null")
+
+        val rotation = getSensorRotationRelativeToCaptureTargetRotation()
+        return if (rotation == 90 || rotation == 270) {
+            Size(resolution.height, resolution.width)
+        } else {
+            resolution
+        }
+    }
     // endregion
 
     companion object {
@@ -279,7 +298,7 @@
 
         private const val TAG = "MainActivity"
         private const val REQUEST_CODE_PERMISSIONS = 20
-        private val PERMISSIONS =
-            arrayOf(Manifest.permission.CAMERA)
+        val PERMISSIONS =
+            arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
     }
 }
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureResult.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureResult.kt
new file mode 100644
index 0000000..2dec4dd
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureResult.kt
@@ -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.integration.uiwidgets.rotations
+
+import android.content.ContentResolver
+import android.net.Uri
+import android.util.Size
+import androidx.camera.core.ImageProxy
+import androidx.camera.core.impl.utils.Exif
+import java.io.File
+
+/** A wrapper around an ImageCapture result, used for testing. */
+sealed class ImageCaptureResult {
+
+    abstract fun getResolution(): Size
+
+    abstract fun getRotation(): Int
+
+    abstract fun delete()
+
+    class InMemory(private val imageProxy: ImageProxy) : ImageCaptureResult() {
+        override fun getResolution() = Size(imageProxy.width, imageProxy.height)
+        override fun getRotation() = imageProxy.imageInfo.rotationDegrees
+        override fun delete() {}
+    }
+
+    class FileOrOutputStream(private val file: File) : ImageCaptureResult() {
+        private val exif = Exif.createFromFile(file)
+        override fun getResolution() = Size(exif.width, exif.height)
+        override fun getRotation() = exif.rotation
+        override fun delete() {
+            file.delete()
+        }
+    }
+
+    class MediaStore(private val contentResolver: ContentResolver, private val uri: Uri) :
+        ImageCaptureResult() {
+
+        private val exif: Exif
+
+        init {
+            val inputStream = contentResolver.openInputStream(uri)
+            exif = Exif.createFromInputStream(inputStream!!)
+        }
+
+        override fun getResolution() = Size(exif.width, exif.height)
+        override fun getRotation() = exif.rotation
+        override fun delete() {
+            contentResolver.delete(uri, null, null)
+        }
+    }
+}
\ No newline at end of file
diff --git a/collection/collection-benchmark/src/androidTest/AndroidManifest.xml b/collection/collection-benchmark/src/androidTest/AndroidManifest.xml
index 0e6ce1e..1664e8d 100644
--- a/collection/collection-benchmark/src/androidTest/AndroidManifest.xml
+++ b/collection/collection-benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
diff --git a/compose/compose-compiler-hosted/integration-tests/build.gradle b/compose/compose-compiler-hosted/integration-tests/build.gradle
index 8b77232..6cd123b 100644
--- a/compose/compose-compiler-hosted/integration-tests/build.gradle
+++ b/compose/compose-compiler-hosted/integration-tests/build.gradle
@@ -40,6 +40,7 @@
     testImplementation(project(":ui:ui-core"))
     testImplementation(project(":ui:ui-android-view"))
     testImplementation(project(":compose:compose-compiler-hosted"))
+    testImplementation("androidx.core:core-ktx:1.1.0")
 }
 
 android {
@@ -65,6 +66,7 @@
 tasks.withType(KotlinCompile).configureEach {
     kotlinOptions {
         jvmTarget = "1.8"
+        freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn"]
     }
 }
 
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt
index da5b3a2..d93f5ee 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt
@@ -139,7 +139,7 @@
                 import androidx.compose.*
                 import android.widget.LinearLayout
                 import android.content.Context
-                import androidx.ui.node.UiComposer
+                import androidx.ui.node.UiApplier
 
                 $src
 
@@ -150,12 +150,12 @@
 
                 private var __context: Context? = null
 
+                @OptIn(ExperimentalComposeApi::class)
                 fun makeComposer(): Composer<*> {
                     val container = LinearLayout(__context!!)
-                    return UiComposer(
-                        __context!!,
-                        container,
+                    return Composer(
                         SlotTable(),
+                        UiApplier(container),
                         Recomposer.current()
                     )
                 }
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt
index 7e7f8ff..320a230 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt
@@ -116,6 +116,80 @@
         if (dumpClasses) dumpClasses(loader)
     }
 
+    protected val COMPOSE_VIEW_STUBS_IMPORTS = """
+        import android.view.View
+        import android.widget.TextView
+        import android.widget.Button
+        import android.view.Gravity
+        import android.widget.LinearLayout
+        import androidx.compose.Composable
+        import androidx.ui.viewinterop.emitView
+    """.trimIndent()
+
+    protected val COMPOSE_VIEW_STUBS = """
+        @Composable
+        fun TextView(
+            id: Int = 0,
+            gravity: Int = Gravity.TOP or Gravity.START,
+            text: String = "",
+            onClick: (() -> Unit)? = null,
+            onClickListener: View.OnClickListener? = null
+        ) {
+            emitView(::TextView) {
+                if (id != 0) it.id = id
+                it.text = text
+                it.gravity = gravity
+                if (onClickListener != null) it.setOnClickListener(onClickListener)
+                if (onClick != null) it.setOnClickListener(View.OnClickListener { onClick() })
+            }
+        }
+
+        @Composable
+        fun Button(
+            id: Int = 0,
+            text: String = "",
+            onClick: (() -> Unit)? = null,
+            onClickListener: View.OnClickListener? = null
+        ) {
+            emitView(::Button) {
+                if (id != 0) it.id = id
+                it.text = text
+                if (onClickListener != null) it.setOnClickListener(onClickListener)
+                if (onClick != null) it.setOnClickListener(View.OnClickListener { onClick() })
+            }
+        }
+
+        @Composable
+        fun LinearLayout(
+            id: Int = 0,
+            orientation: Int = LinearLayout.VERTICAL,
+            onClickListener: View.OnClickListener? = null,
+            children: @Composable () -> Unit
+        ) {
+            emitView(
+                ::LinearLayout,
+                {
+                    if (id != 0) it.id = id
+                    if (onClickListener != null) it.setOnClickListener(onClickListener)
+                    it.orientation = orientation
+                },
+                children
+            )
+        }
+    """.trimIndent()
+
+    protected fun testCompileWithViewStubs(source: String, dumpClasses: Boolean = false) =
+        testCompile(
+        """
+            $COMPOSE_VIEW_STUBS_IMPORTS
+
+            $source
+
+            $COMPOSE_VIEW_STUBS
+        """,
+        dumpClasses
+    )
+
     protected fun testCompileEmittable(source: String, dumpClasses: Boolean = false) = testCompile(
         """
         @file:OptIn(
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt
index 81cd9d8..6e62935 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt
@@ -83,18 +83,18 @@
             ) {
                 "${it.groupValues[1]}<>"
             }
-            // restartableFunctionInstance(<>, true)
+            // composableLambdaInstance(<>, true)
             .replace(
                 Regex(
-                    "(restartableFunctionInstance\\()([-\\d]+)"
+                    "(composableLambdaInstance\\()([-\\d]+)"
                 )
             ) {
                 "${it.groupValues[1]}<>"
             }
-            // restartableFunction(%composer, <>, true)
+            // composableLambda(%composer, <>, true)
             .replace(
                 Regex(
-                    "(restartableFunction\\(%composer,\\s)([-\\d]+)"
+                    "(composableLambda\\(%composer,\\s)([-\\d]+)"
                 )
             ) {
                 "${it.groupValues[1]}<>"
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt
index a5b9329..5cd2dbb 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt
@@ -16,8 +16,9 @@
 
 package androidx.compose.plugins.kotlin
 
+import android.view.View
 import androidx.compose.Composer
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
+import org.robolectric.RuntimeEnvironment
 import java.net.URLClassLoader
 
 abstract class AbstractLoweringTests : AbstractCodegenTest() {
@@ -28,12 +29,25 @@
            import android.content.Context
            import android.widget.*
            import androidx.compose.*
+           $COMPOSE_VIEW_STUBS_IMPORTS
 
            $text
 
+           $COMPOSE_VIEW_STUBS
+
         """, dumpClasses)
     }
 
+    @Suppress("UNCHECKED_CAST")
+    fun View.getComposedSet(tagId: Int): Set<String>? = getTag(tagId) as? Set<String>
+
+    protected fun execute(block: () -> Unit) {
+        val scheduler = RuntimeEnvironment.getMasterScheduler()
+        scheduler.pause()
+        block()
+        scheduler.advanceToLastPostedRunnable()
+    }
+
     fun codegenNoImports(text: String, dumpClasses: Boolean = false) {
         val className = "Test_${uniqueNumber++}"
         val fileName = "$className.kt"
@@ -64,11 +78,12 @@
 
         val compiledClasses = classLoader(
             """
-       import android.content.Context
        import android.widget.*
        import androidx.compose.*
        import androidx.ui.androidview.adapters.*
 
+       $COMPOSE_VIEW_STUBS_IMPORTS
+
        $supportingCode
 
        class $className {
@@ -78,6 +93,8 @@
            $composeCode
          }
        }
+
+       $COMPOSE_VIEW_STUBS
     """, fileName, dumpClasses
         )
 
@@ -112,23 +129,7 @@
         return compose { composer, _, _ ->
             val values = valuesFactory()
             val arguments = values.map { it.value }.toTypedArray()
-            testMethod.invoke(instanceOfClass, *arguments, composer, 0, 0)
+            testMethod.invoke(instanceOfClass, *arguments, composer, 0, 1)
         }
     }
-
-    private fun ResolvedCall<*>.isEmit(): Boolean = candidateDescriptor is ComposableEmitDescriptor
-    private fun ResolvedCall<*>.isCall(): Boolean =
-        candidateDescriptor is ComposableFunctionDescriptor
-
-    private val callPattern = Regex("(<normal>)|(<emit>)|(<call>)")
-    private fun extractCarets(text: String): Pair<String, List<Pair<Int, String>>> {
-        val indices = mutableListOf<Pair<Int, String>>()
-        var offset = 0
-        val src = callPattern.replace(text) {
-            indices.add(it.range.first - offset to it.value)
-            offset += it.range.last - it.range.first + 1
-            ""
-        }
-        return src to indices
-    }
 }
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt
index b660a32d..ca93902 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt
@@ -21,11 +21,6 @@
 import android.widget.TextView
 import com.intellij.psi.PsiElement
 import com.intellij.psi.util.PsiTreeUtil
-import org.jetbrains.kotlin.psi.KtCallExpression
-import org.jetbrains.kotlin.psi.KtFile
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.annotation.Config
@@ -253,10 +248,7 @@
     fun testReceiverLambdaInvocation(): Unit = ensureSetup {
         codegen(
             """
-                import androidx.compose.*
-                import androidx.ui.node.UiComposer
-
-                class TextSpanScope internal constructor(val composer: UiComposer)
+                class TextSpanScope
 
                 @Composable fun TextSpanScope.Foo(children: @Composable TextSpanScope.() -> Unit) {
                     children()
@@ -291,7 +283,6 @@
         codegen(
             """
                 import androidx.compose.*
-                import android.widget.LinearLayout
 
                 @Composable
                 inline fun PointerInputWrapper(
@@ -311,12 +302,12 @@
         codegenNoImports(
             """
         import androidx.compose.Composable
-        import android.widget.LinearLayout
+
+        @Composable fun Wrap(content: @Composable () -> Unit) { content() }
 
         @Composable
         fun Foo() {
-            // emits work
-            LinearLayout {
+            Wrap {
                 // nested calls work
                 Bar()
             }
@@ -326,7 +317,6 @@
 
         @Composable
         fun Bar() {}
-
             """.trimIndent()
         )
     }
@@ -374,47 +364,6 @@
     }
 
     @Test
-    fun testSetViewContentIssue(): Unit = ensureSetup {
-        codegen(
-            """
-                import android.app.Activity
-                import android.os.Bundle
-                import android.view.Gravity
-                import android.view.ViewGroup
-                import android.widget.*
-                import androidx.compose.*
-                import androidx.ui.core.setViewContent
-                import androidx.ui.androidview.adapters.*
-
-                class RippleActivity : Activity() {
-
-                    override fun onCreate(savedInstanceState: Bundle?) {
-                        super.onCreate(savedInstanceState)
-                        setViewContent {
-                            val layoutParams = LinearLayout.LayoutParams(
-                                ViewGroup.LayoutParams.MATCH_PARENT,
-                                0,
-                                1f
-                            )
-                            val gravity = Gravity.CENTER_HORIZONTAL
-                            LinearLayout(orientation = LinearLayout.VERTICAL) {
-                                TextView(gravity = gravity, text = "Compose card with ripple:")
-                                LinearLayout(layoutParams = layoutParams) {
-                                    // RippleDemo()
-                                }
-                                TextView(gravity = gravity, text = "Platform button with ripple:")
-                                LinearLayout(layoutParams = layoutParams, padding = 50.dp) {
-                                    // Button(background = getDrawable(R.drawable.ripple))
-                                }
-                            }
-                        }
-                    }
-                }
-            """
-        )
-    }
-
-    @Test
     fun testGenericParameterOrderIssue(): Unit = ensureSetup {
         codegen(
             """
@@ -472,37 +421,6 @@
     }
 
     @Test
-    fun testWebViewBug(): Unit = ensureSetup {
-        codegen(
-            """
-import android.webkit.WebView
-import android.webkit.WebViewClient
-import androidx.compose.Composable
-
-class WebContext {
-    var webView: WebView? = null
-}
-
-private fun WebView.setRef(ref: (WebView) -> Unit) {
-    ref(this)
-}
-
-@Composable
-fun WebComponent(
-    url: String,
-    webViewClient: WebViewClient = WebViewClient(),
-    webContext: WebContext
-) {
-
-    WebView(
-        ref = { webContext.webView = it }
-    )
-}
-            """
-        )
-    }
-
-    @Test
     fun testStuffThatIWantTo(): Unit = ensureSetup {
         codegen(
             """
@@ -543,7 +461,6 @@
     fun testSimpleClassResolution(): Unit = ensureSetup {
         compose(
             """
-            import android.widget.TextView
             import androidx.compose.*
 
             @Composable
@@ -596,9 +513,7 @@
     fun testObservable(): Unit = ensureSetup {
         compose(
             """
-                import android.widget.Button
                 import androidx.compose.*
-                import androidx.ui.androidview.adapters.setOnClick
 
                 @Composable
                 fun SimpleComposable() {
@@ -981,27 +896,6 @@
     }
 
     @Test
-    fun testInliningTemp(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(x: Double, children: @Composable Double.() -> Unit) {
-                  x.children()
-                }
-            """,
-            """
-                Foo(x=1.0) {
-                    TextView(text=this.toString(), id=123)
-                }
-            """,
-            { mapOf("foo" to "bar") }
-        ).then { activity ->
-            val textView = activity.findViewById(123) as TextView
-            assertEquals("1.0", textView.text)
-        }
-    }
-
-    @Test
     fun testInliningTemp2(): Unit = ensureSetup {
         compose(
             """
@@ -1148,33 +1042,1542 @@
         )
     }
 
-    private fun ResolvedCall<*>.isEmit(): Boolean = candidateDescriptor is ComposableEmitDescriptor
-    private fun ResolvedCall<*>.isCall(): Boolean =
-        candidateDescriptor is ComposableFunctionDescriptor
+    @Test
+    fun testReturnValue(): Unit = ensureSetup {
+        compose("""
+            var a = 0
+            var b = 0
 
-    private val callPattern = Regex("(<normal>)|(<emit>)|(<call>)")
-    private fun extractCarets(text: String): Pair<String, List<Pair<Int, String>>> {
-        val indices = mutableListOf<Pair<Int, String>>()
-        var offset = 0
-        val src = callPattern.replace(text) {
-            indices.add(it.range.first - offset to it.value)
-            offset += it.range.last - it.range.first + 1
-            ""
+            @Composable
+            fun SimpleComposable() {
+                a++
+                val c = state { 0 }
+                val d = remember(c.value) { b++; b }
+                val recompose = invalidate
+                Button(
+                  text=listOf(a, b, c.value, d).joinToString(", "),
+                  onClick={ c.value += 1 },
+                  id=42
+                )
+                Button(
+                  text="Recompose",
+                  onClick={ recompose() },
+                  id=43
+                )
+            }
+        """,
+            "SimpleComposable()",
+            noParameters
+        ).then { activity ->
+            val button = activity.findViewById(42) as Button
+            assertEquals(
+                button.text,
+                listOf(
+                    1, // SimpleComposable has run once
+                    1, // memo has been called once because of initial mount
+                    0, // state was in itialized at 0
+                    1 // memo should return b
+                ).joinToString(", ")
+            )
+            button.performClick()
+        }.then { activity ->
+            val button = activity.findViewById(42) as Button
+            val recompose = activity.findViewById(43) as Button
+            assertEquals(
+                button.text,
+                listOf(
+                    2, // SimpleComposable has run twice
+                    2, // memo has been called twice, because state input has changed
+                    1, // state was changed to 1
+                    2 // memo should return b
+                ).joinToString(", ")
+            )
+            recompose.performClick()
+        }.then { activity ->
+            val button = activity.findViewById(42) as Button
+            assertEquals(
+                button.text,
+                listOf(
+                    3, // SimpleComposable has run three times
+                    2, // memo was not called this time, because input didn't change
+                    1, // state stayed at 1
+                    2 // memo should return b
+                ).joinToString(", ")
+            )
         }
-        return src to indices
     }
 
-    private fun resolvedCallAtOffset(
-        bindingContext: BindingContext,
-        jetFile: KtFile,
-        index: Int
-    ): ResolvedCall<*>? {
-        val element = jetFile.findElementAt(index)!!
-        val callExpression = element.parentOfType<KtCallExpression>()
-        return callExpression?.getResolvedCall(bindingContext)
+    @Test
+    fun testReorderedArgsReturnValue(): Unit = ensureSetup {
+        compose(
+            """
+            @Composable
+            fun SimpleComposable() {
+                val x = remember(calculation = { "abc" }, v1 = "def")
+                TextView(
+                  text=x,
+                  id=42
+                )
+            }
+        """,
+            "SimpleComposable()",
+            noParameters
+        ).then { activity ->
+            val button = activity.findViewById(42) as TextView
+            assertEquals(button.text, "abc")
+        }
+    }
+
+    @Test
+    fun testTrivialReturnValue(): Unit = ensureSetup {
+        compose("""
+        @Composable
+        fun <T> identity(value: T): T = value
+
+        @Composable
+        fun SimpleComposable() {
+            val x = identity("def")
+            TextView(
+              text=x,
+              id=42
+            )
+        }
+    """,
+            "SimpleComposable()",
+            noParameters
+        ).then { activity ->
+            val button = activity.findViewById(42) as TextView
+            assertEquals(button.text, "def")
+        }
+    }
+
+    @Test
+    fun testForDevelopment(): Unit = ensureSetup {
+        codegen(
+            """
+            import androidx.compose.*
+
+            @Composable
+            fun bar() {
+
+            }
+
+            @Composable
+            fun foo() {
+                TextView(text="Hello World")
+            }
+            """
+        )
+    }
+
+    @Test
+    fun testInliningTemp(): Unit = ensureSetup {
+        compose(
+            """
+                @Composable
+                fun Foo(x: Double, children: @Composable Double.() -> Unit) {
+                  x.children()
+                }
+            """,
+            """
+                Foo(x=1.0) {
+                    TextView(text=this.toString(), id=123)
+                }
+            """,
+            { mapOf("foo" to "bar") }
+        ).then { activity ->
+            val textView = activity.findViewById(123) as TextView
+            assertEquals("1.0", textView.text)
+        }
+    }
+
+    @Test
+    fun testCGUpdatedComposition(): Unit = ensureSetup {
+        var value = "Hello, world!"
+
+        compose(
+            """""",
+            """
+               TextView(text=value, id=42)
+            """,
+            { mapOf("value" to value) }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+
+            value = "Other value"
+        }.then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Other value", textView.text)
+        }
+    }
+
+    @Test
+    fun testCGNUpdatedComposition(): Unit = ensureSetup {
+        var value = "Hello, world!"
+
+        compose(
+            """""",
+            """
+               TextView(text=value, id=42)
+            """,
+            { mapOf("value" to value) }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+
+            value = "Other value"
+        }.then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Other value", textView.text)
+        }
+    }
+
+    @Test
+    fun testCGViewGroup(): Unit = ensureSetup {
+        val tvId = 258
+        val llId = 260
+        var text = "Hello, world!"
+        var orientation = LinearLayout.HORIZONTAL
+
+        compose(
+            """""",
+            """
+                LinearLayout(orientation=orientation, id=$llId) {
+                  TextView(text=text, id=$tvId)
+                }
+            """,
+            { mapOf("text" to text, "orientation" to orientation) }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val linearLayout = activity.findViewById(llId) as LinearLayout
+
+            assertEquals(text, textView.text)
+            assertEquals(orientation, linearLayout.orientation)
+
+            text = "Other value"
+            orientation = LinearLayout.VERTICAL
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val linearLayout = activity.findViewById(llId) as LinearLayout
+
+            assertEquals(text, textView.text)
+            assertEquals(orientation, linearLayout.orientation)
+        }
+    }
+
+    @Test
+    fun testCGNFunctionComponent(): Unit = ensureSetup {
+        var text = "Hello, world!"
+        val tvId = 123
+
+        compose(
+            """
+            @Composable
+            fun Foo(text: String) {
+                TextView(id=$tvId, text=text)
+            }
+
+        """,
+            """
+             Foo(text=text)
+        """,
+            { mapOf("text" to text) }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+
+            assertEquals(text, textView.text)
+            text = "wat"
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+
+            assertEquals(text, textView.text)
+        }
+    }
+
+    @Test
+    fun testAmbientConsumedFromDefaultParameter(): Unit = ensureSetup {
+        val initialText = "no text"
+        val helloWorld = "Hello World!"
+        compose("""
+            val TextAmbient = ambientOf { "$initialText" }
+
+            @Composable
+            fun Main() {
+                var text = state { "$initialText" }
+                Providers(TextAmbient provides text.value) {
+                    LinearLayout {
+                        ConsumesAmbientFromDefaultParameter()
+                        Button(
+                            text = "Change ambient value",
+                            onClick={ text.value = "$helloWorld" },
+                            id=101
+                        )
+                    }
+                }
+            }
+
+            @Composable
+            fun ConsumesAmbientFromDefaultParameter(text: String = TextAmbient.current) {
+                TextView(text = text, id = 42)
+            }
+        """,
+            "Main()",
+            noParameters
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals(initialText, textView.text)
+        }.then { activity ->
+            val button = activity.findViewById(101) as Button
+            button.performClick()
+        }
+            .then { activity ->
+                val textView = activity.findViewById(42) as TextView
+                assertEquals(helloWorld, textView.text)
+            }
+    }
+
+    @Test
+    fun testCGNViewGroup(): Unit = ensureSetup {
+        val tvId = 258
+        val llId = 260
+        var text = "Hello, world!"
+        var orientation = LinearLayout.HORIZONTAL
+
+        compose(
+            """""",
+            """
+                 LinearLayout(orientation=orientation, id=$llId) {
+                   TextView(text=text, id=$tvId)
+                 }
+            """,
+            { mapOf("text" to text, "orientation" to orientation) }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val linearLayout = activity.findViewById(llId) as LinearLayout
+
+            assertEquals(text, textView.text)
+            assertEquals(orientation, linearLayout.orientation)
+
+            text = "Other value"
+            orientation = LinearLayout.VERTICAL
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val linearLayout = activity.findViewById(llId) as LinearLayout
+
+            assertEquals(text, textView.text)
+            assertEquals(orientation, linearLayout.orientation)
+        }
+    }
+
+    @Test
+    fun testMemoization(): Unit = ensureSetup {
+        val tvId = 258
+        val tagId = (3 shl 24) or "composed_set".hashCode()
+
+        compose(
+            """
+                var composedSet = mutableSetOf<String>()
+                var inc = 1
+
+                @Composable fun ComposedTextView(id: Int, composed: Set<String>) {
+                  emitView(::TextView) {
+                    it.id = id
+                    it.setTag($tagId, composed)
+                  }
+                }
+
+                @Composable fun ComposePrimitive(value: Int) {
+                    composedSet.add("ComposePrimitive(" + value + ")")
+                }
+
+                class MutableThing(var value: String)
+
+                val constantMutableThing = MutableThing("const")
+
+                @Composable fun ComposeMutable(value: MutableThing) {
+                    composedSet.add("ComposeMutable(" + value.value + ")")
+                }
+            """,
+            """
+                composedSet.clear()
+
+                ComposePrimitive(value=123)
+                ComposePrimitive(value=inc)
+                ComposeMutable(value=constantMutableThing)
+                ComposeMutable(value=MutableThing("new"))
+
+                ComposedTextView(id=$tvId, composed=composedSet)
+
+                inc++
+            """,
+            { mapOf("text" to "") }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val composedSet = textView.getComposedSet(tagId) ?: error(
+                "expected a compose set to exist")
+
+            fun assertContains(contains: Boolean, key: String) {
+                assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
+            }
+
+            assertContains(true, "ComposePrimitive(123)")
+            assertContains(true, "ComposePrimitive(1)")
+            assertContains(true, "ComposeMutable(const)")
+            assertContains(true, "ComposeMutable(new)")
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val composedSet = textView.getComposedSet(tagId)
+                ?: error("expected a compose set to exist")
+
+            fun assertContains(contains: Boolean, key: String) {
+                assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
+            }
+
+            // the primitive component skips based on equality
+            assertContains(false, "ComposePrimitive(123)")
+
+            // since the primitive changed, this one recomposes again
+            assertContains(true, "ComposePrimitive(2)")
+
+            // since this is a potentially mutable object, we don't skip based on it
+            assertContains(true, "ComposeMutable(const)")
+
+            // since it's a new one every time, we definitely don't skip
+            assertContains(true, "ComposeMutable(new)")
+        }
+    }
+
+    @Test
+    fun testInlineClassMemoization(): Unit = ensureSetup {
+        val tvId = 258
+        val tagId = (3 shl 24) or "composed_set".hashCode()
+
+        compose(
+            """
+                inline class InlineInt(val value: Int)
+                inline class InlineInlineInt(val value: InlineInt)
+                inline class InlineMutableSet(val value: MutableSet<String>)
+                @Composable fun ComposedTextView(id: Int, composed: Set<String>) {
+                  emitView(::TextView) {
+                    it.id = id
+                    it.setTag($tagId, composed)
+                  }
+                }
+
+                val composedSet = mutableSetOf<String>()
+                val constInlineInt = InlineInt(0)
+                var inc = 2
+                val constInlineMutableSet = InlineMutableSet(mutableSetOf("a"))
+
+                @Composable fun ComposedInlineInt(value: InlineInt) {
+                  composedSet.add("ComposedInlineInt(" + value + ")")
+                }
+
+                @Composable fun ComposedInlineInlineInt(value: InlineInlineInt) {
+                  composedSet.add("ComposedInlineInlineInt(" + value + ")")
+                }
+
+                @Composable fun ComposedInlineMutableSet(value: InlineMutableSet) {
+                  composedSet.add("ComposedInlineMutableSet(" + value + ")")
+                }
+            """,
+            """
+                composedSet.clear()
+
+                ComposedInlineInt(constInlineInt)
+                ComposedInlineInt(InlineInt(1))
+                ComposedInlineInt(InlineInt(inc))
+                ComposedInlineInlineInt(InlineInlineInt(InlineInt(2)))
+                ComposedInlineMutableSet(constInlineMutableSet)
+
+                ComposedTextView(id=$tvId, composed=composedSet)
+
+                inc++
+            """,
+            { mapOf("text" to "") }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val composedSet = textView.getComposedSet(tagId)
+                ?: error("expected a compose set to exist")
+
+            // All composables should execute since it's the first time.
+            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
+            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
+            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=2))"))
+            assert(composedSet.contains(
+                "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
+            assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val composedSet = textView.getComposedSet(tagId)
+                ?: error("expected a compose set to exist")
+
+            // InlineInt and InlineInlineInt are stable, so the corresponding composables should
+            // not run for values equal to previous compositions.
+            assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
+            assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
+            assert(!composedSet.contains(
+                "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
+
+            // But if a stable composable is passed a new value, it should re-run.
+            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=3))"))
+
+            // And composables for inline classes with non-stable underlying types should run.
+            assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
+        }
+    }
+
+    @Test
+    fun testStringParameterMemoization(): Unit = ensureSetup {
+        val tvId = 258
+        val tagId = (3 shl 24) or "composed_set".hashCode()
+
+        compose(
+            """
+                @Composable fun ComposedTextView(id: Int, composed: Set<String>) {
+                  emitView(::TextView) {
+                    it.id = id
+                    it.setTag($tagId, composed)
+                  }
+                }
+
+                val composedSet = mutableSetOf<String>()
+                val FOO = "foo"
+
+                @Composable fun ComposedString(value: String) {
+                  composedSet.add("ComposedString(" + value + ")")
+                }
+            """,
+            """
+                composedSet.clear()
+
+                ComposedString(FOO)
+                ComposedString("bar")
+
+                ComposedTextView(id=$tvId, composed=composedSet)
+            """,
+            { mapOf("text" to "") }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val composedSet = textView.getComposedSet(tagId)
+                ?: error("expected a compose set to exist")
+
+            // All composables should execute since it's the first time.
+            assert(composedSet.contains("ComposedString(foo)"))
+            assert(composedSet.contains("ComposedString(bar)"))
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            val composedSet = textView.getComposedSet(tagId)
+                ?: error("expected a compose set to exist")
+
+            assert(composedSet.isEmpty())
+        }
+    }
+
+    @Test
+    fun testCGNSimpleCall(): Unit = ensureSetup {
+        val tvId = 258
+        var text = "Hello, world!"
+
+        compose(
+            """
+                @Composable fun SomeFun(x: String) {
+                    TextView(text=x, id=$tvId)
+                }
+            """,
+            """
+                SomeFun(x=text)
+            """,
+            { mapOf("text" to text) }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+
+            assertEquals(text, textView.text)
+
+            text = "Other value"
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+
+            assertEquals(text, textView.text)
+        }
+    }
+
+    @Test
+    fun testCGNCallWithChildren(): Unit = ensureSetup {
+        val tvId = 258
+        var text = "Hello, world!"
+
+        compose(
+            """
+                @Composable
+                fun Block(children: @Composable () -> Unit) {
+                    children()
+                }
+            """,
+            """
+                Block {
+                    Block {
+                        TextView(text=text, id=$tvId)
+                    }
+                }
+            """,
+            { mapOf("text" to text) }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+
+            assertEquals(text, textView.text)
+
+            text = "Other value"
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+
+            assertEquals(text, textView.text)
+        }
+    }
+
+    @Test
+    fun testCGComposableFunctionInvocationOneParameter(): Unit = ensureSetup {
+        val tvId = 91
+        var phone = "(123) 456-7890"
+        compose(
+            """
+           @Composable
+           fun Phone(value: String) {
+             TextView(text=value, id=$tvId)
+           }
+        """,
+        """
+           Phone(value=phone)
+        """,
+            { mapOf("phone" to phone) }
+        ).then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            assertEquals(phone, textView.text)
+
+            phone = "(123) 456-7899"
+        }.then { activity ->
+            val textView = activity.findViewById(tvId) as TextView
+            assertEquals(phone, textView.text)
+        }
+    }
+
+    @Test
+    fun testCGComposableFunctionInvocationTwoParameters(): Unit = ensureSetup {
+        val tvId = 111
+        val rsId = 112
+        var left = 0
+        var right = 0
+        compose(
+            """
+           var addCalled = 0
+
+           @Composable
+           fun AddView(left: Int, right: Int) {
+             addCalled++
+             TextView(text="${'$'}left + ${'$'}right = ${'$'}{left + right}", id=$tvId)
+             TextView(text="${'$'}addCalled", id=$rsId)
+           }
+        """, """
+           AddView(left=left, right=right)
+        """,
+            { mapOf("left" to left, "right" to right) }
+        ).then { activity ->
+            // Should be called on the first compose
+            assertEquals("1", (activity.findViewById(rsId) as TextView).text)
+            assertEquals(
+                "$left + $right = ${left + right}",
+                (activity.findViewById(tvId) as TextView).text
+            )
+        }.then { activity ->
+            // Should be skipped on the second compose
+            assertEquals("1", (activity.findViewById(rsId) as TextView).text)
+            assertEquals(
+                "$left + $right = ${left + right}",
+                (activity.findViewById(tvId) as TextView).text
+            )
+
+            left = 1
+        }.then { activity ->
+            // Should be called again because left changed.
+            assertEquals("2", (activity.findViewById(rsId) as TextView).text)
+            assertEquals(
+                "$left + $right = ${left + right}",
+                (activity.findViewById(tvId) as TextView).text
+            )
+
+            right = 41
+        }.then { activity ->
+            // Should be called again because right changed
+            assertEquals("3", (activity.findViewById(rsId) as TextView).text)
+            assertEquals(
+                "$left + $right = ${left + right}",
+                (activity.findViewById(tvId) as TextView).text
+            )
+        }.then { activity ->
+            // Should be skipped because nothing changed
+            assertEquals("3", (activity.findViewById(rsId) as TextView).text)
+        }
+    }
+
+    @Test
+    fun testImplicitReceiverPassing1(): Unit = ensureSetup {
+        compose(
+            """
+                @Composable fun Int.Foo(x: @Composable Int.() -> Unit) {
+                    x()
+                }
+            """,
+            """
+                val id = 42
+
+                id.Foo(x={
+                    TextView(text="Hello, world!", id=this)
+                })
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    @Test
+    fun testImplicitReceiverPassing2(): Unit = ensureSetup {
+        compose(
+            """
+                @Composable fun Int.Foo(x: @Composable Int.(text: String) -> Unit, text: String) {
+                    x(text=text)
+                }
+
+                @Composable fun MyText(text: String, id: Int) {
+                    TextView(text=text, id=id)
+                }
+            """,
+            """
+                val id = 42
+
+                id.Foo(text="Hello, world!", x={ text ->
+                    MyText(text=text, id=this)
+                })
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    @Test
+    fun testEffects1(): Unit = ensureSetup {
+        compose(
+            """
+                import androidx.ui.androidview.adapters.*
+
+                @Composable
+                fun Counter() {
+                    var count = state { 0 }
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
+                }
+            """,
+            """
+                Counter()
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Count: 0", textView.text)
+            textView.performClick()
+        }.then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Count: 1", textView.text)
+        }
+    }
+
+    @Test
+    fun testEffects2(): Unit = ensureSetup {
+        compose(
+            """
+                import androidx.ui.androidview.adapters.*
+
+                @Composable
+                fun Counter() {
+                    var count = state { 0 }
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
+                }
+            """,
+            """
+                Counter()
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Count: 0", textView.text)
+            textView.performClick()
+        }.then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Count: 1", textView.text)
+        }
+    }
+
+    @Test
+    fun testEffects3(): Unit = ensureSetup {
+        val log = StringBuilder()
+        compose(
+            """
+                import androidx.ui.androidview.adapters.*
+
+                @Composable
+                fun Counter(log: StringBuilder) {
+                    var count = state { 0 }
+                    onCommit {
+                        log.append("a")
+                    }
+                    onActive {
+                        log.append("b")
+                    }
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
+                }
+            """,
+            """
+                Counter(log=log)
+            """,
+            { mapOf("log" to log) }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Count: 0", textView.text)
+            assertEquals("ab", log.toString())
+
+            execute {
+                textView.performClick()
+            }
+
+            assertEquals("Count: 1", textView.text)
+            assertEquals("aba", log.toString())
+        }
+    }
+
+    @Test
+    fun testEffects4(): Unit = ensureSetup {
+        val log = StringBuilder()
+        compose(
+            """
+                import androidx.ui.androidview.adapters.*
+
+                @Composable
+                fun printer(log: StringBuilder, str: String) {
+                    onCommit {
+                        log.append(str)
+                    }
+                }
+
+                @Composable
+                fun Counter(log: StringBuilder) {
+                    var count = state { 0 }
+                    printer(log, "" + count.value)
+                    TextView(
+                        text=("Count: " + count.value),
+                        onClick={
+                            count.value += 1
+                        },
+                        id=42
+                    )
+                }
+            """,
+            """
+                Counter(log=log)
+            """,
+            { mapOf("log" to log) }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Count: 0", textView.text)
+            assertEquals("0", log.toString())
+
+            execute {
+                textView.performClick()
+            }
+
+            assertEquals("Count: 1", textView.text)
+            assertEquals("01", log.toString())
+        }
+    }
+
+    @Test
+    fun testVariableCalls1(): Unit = ensureSetup {
+        compose(
+            """
+                val component = @Composable {
+                    TextView(text="Hello, world!", id=42)
+                }
+            """,
+            """
+                component()
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    @Test
+    fun testVariableCalls2(): Unit = ensureSetup {
+        compose(
+            """
+                val component = @Composable {
+                    TextView(text="Hello, world!", id=42)
+                }
+                class HolderA(val composable: @Composable () -> Unit)
+
+                val holder = HolderA(component)
+
+            """,
+            """
+                holder.composable()
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    @Test
+    fun testVariableCalls3(): Unit = ensureSetup {
+        compose(
+            """
+                val component = @Composable {
+                    TextView(text="Hello, world!", id=42)
+                }
+                class HolderB(val composable: @Composable () -> Unit) {
+                    @Composable
+                    fun Foo() {
+                        composable()
+                    }
+                }
+
+                val holder = HolderB(component)
+
+            """,
+            """
+                holder.Foo()
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    // b/123721921
+    @Test
+    fun testDefaultParameters1(): Unit = ensureSetup {
+        compose(
+            """
+                @Composable
+                fun Foo(a: Int = 42, b: String) {
+                    TextView(text=b, id=a)
+                }
+            """,
+            """
+                Foo(b="Hello, world!")
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    @Test
+    fun testDefaultParameters2(): Unit = ensureSetup {
+        compose(
+            """
+                @Composable
+                fun Foo(a: Int = 42, b: String, c: @Composable () -> Unit) {
+                    c()
+                    TextView(text=b, id=a)
+                }
+            """,
+            """
+                Foo(b="Hello, world!") {}
+            """,
+            { mapOf<String, String>() }
+        ).then { activity ->
+            val textView = activity.findViewById(42) as TextView
+            assertEquals("Hello, world!", textView.text)
+        }
+    }
+
+    @Test
+    fun testMovement(): Unit = ensureSetup {
+        val tvId = 50
+        val btnIdAdd = 100
+        val btnIdUp = 200
+        val btnIdDown = 300
+
+        // Duplicate the steps to reproduce an issue discovered in the Reorder example
+        compose(
+            """
+            fun <T> List<T>.move(from: Int, to: Int): List<T> {
+                if (to < from) return move(to, from)
+                val item = get(from)
+                val currentItem = get(to)
+                val left = if (from > 0) subList(0, from) else emptyList()
+                val right = if (to < size) subList(to + 1, size) else emptyList()
+                val middle = if (to - from > 1) subList(from + 1, to) else emptyList()
+                return left + listOf(currentItem) + middle + listOf(item) + right
+            }
+
+            @Composable
+            fun Reordering() {
+                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)
+                                    }
+                                }
+                            )
+                        }
+                    }
+                }
+            }
+
+            @Composable
+            // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
+            fun Item(id: Int, onMove: (Int) -> Unit) {
+                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) })
+                }
+            }
+            """,
+            """
+               Reordering()
+            """, noParameters
+        ).then { activity ->
+            // Click 5 add
+            val button = activity.findViewById(btnIdAdd + 5) as Button
+            button.performClick()
+        }.then { activity ->
+            // Click 5 down
+            val button = activity.findViewById(btnIdDown + 5) as Button
+            button.performClick()
+        }.then { activity ->
+            // Click 5 down
+            val button = activity.findViewById(btnIdDown + 5) as Button
+            button.performClick()
+        }.then { activity ->
+            // Click 5 up
+            val button = activity.findViewById(btnIdUp + 5) as Button
+            button.performClick()
+        }.then { activity ->
+            // Click 5 up
+            val button = activity.findViewById(btnIdUp + 5) as Button
+            button.performClick()
+        }.then { activity ->
+            // Click 5 add
+            val button = activity.findViewById(btnIdAdd + 5) as Button
+            button.performClick()
+        }.then { activity ->
+            val textView = activity.findViewById(tvId + 5) as TextView
+            assertEquals("id: 5 amt: 2", textView.text)
+        }
+    }
+
+    @Test
+    fun testObserveKtxWithInline(): Unit = ensureSetup {
+        compose(
+            """
+                @Composable
+                fun SimpleComposable() {
+                    val count = state { 1 }
+                    Box {
+                        repeat(count.value) {
+                            Button(text="Increment", onClick={ count.value += 1 }, id=(41+it))
+                        }
+                    }
+                }
+
+                @Composable
+                fun Box(children: @Composable ()->Unit) {
+                    LinearLayout(orientation=LinearLayout.VERTICAL) {
+                        children()
+                    }
+                }
+            """,
+            """
+               SimpleComposable()
+            """, noParameters
+        ).then { activity ->
+            val button = activity.findViewById(41) as Button
+            button.performClick()
+            button.performClick()
+            button.performClick()
+            button.performClick()
+            button.performClick()
+        }.then { activity ->
+            assertNotNull(activity.findViewById(46))
+        }
+    }
+
+    @Test
+    fun testKeyTag(): Unit = ensureSetup {
+        compose(
+            """
+            val list = mutableListOf(0,1,2,3)
+
+            @Composable
+            fun Reordering() {
+                LinearLayout {
+                    Recompose { recompose ->
+                        Button(
+                          id=50,
+                          text="Recompose!",
+                          onClick={ list.add(list.removeAt(0)); recompose(); }
+                        )
+                        LinearLayout(id=100) {
+                            for(id in list) {
+                                key(id) {
+                                    StatefulButton()
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            @Composable
+            // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
+            fun StatefulButton() {
+                val count = state { 0 }
+                Button(text="Clicked ${'$'}{count.value} times!", onClick={ count.value++ })
+            }
+            """,
+            """
+               Reordering()
+            """, noParameters
+        ).then { activity ->
+            val layout = activity.findViewById(100) as LinearLayout
+            layout.getChildAt(0).performClick()
+        }.then { activity ->
+            val recomposeButton = activity.findViewById(50) as Button
+            recomposeButton.performClick()
+        }.then { activity ->
+            val layout = activity.findViewById(100) as LinearLayout
+            assertEquals("Clicked 0 times!", (layout.getChildAt(0) as Button).text)
+            assertEquals("Clicked 0 times!", (layout.getChildAt(1) as Button).text)
+            assertEquals("Clicked 0 times!", (layout.getChildAt(2) as Button).text)
+            assertEquals("Clicked 1 times!", (layout.getChildAt(3) as Button).text)
+        }
+    }
+
+    @Test
+    fun testNonComposeParameters(): Unit = ensureSetup {
+        compose(
+            """
+                class Action(
+                   val s: String = "",
+                   val param: Int,
+                   type: Set<Int> = setOf(),
+                   val action: () -> Unit
+                )
+
+                @Composable
+                fun DefineAction(
+                    onAction: Action = Action(param = 1) {},
+                    children: @Composable ()->Unit
+                 ) { }
+            """,
+            """"""
+        )
+    }
+
+    @Test
+    fun testStableParameters_Various(): Unit = ensureSetup {
+        val output = ArrayList<String>()
+        compose("""
+            val m = mutableStateOf(0)
+
+            @Immutable
+            data class ValueHolder(val value: Int)
+
+            var output = ArrayList<String>()
+
+            class NotStable { val value = 10 }
+
+            @Stable
+            class StableClass {
+                override fun equals(other: Any?) = true
+            }
+
+            enum class EnumState {
+              One,
+              Two
+            }
+
+            val mutableStateType = mutableStateOf(1)
+            val stateType: State<Int> = mutableStateType
+
+            @Composable
+            fun MemoInt(a: Int) {
+              output.add("MemoInt a=${'$'}a")
+              Button(id=101, text="memo ${'$'}a", onClick={ m.value++ })
+            }
+
+            @Composable
+            fun MemoFloat(a: Float) {
+              output.add("MemoFloat")
+              Button(text="memo ${'$'}a")
+            }
+
+            @Composable
+            fun MemoDouble(a: Double) {
+              output.add("MemoDouble")
+              Button(text="memo ${'$'}a")
+            }
+
+            @Composable
+            fun MemoNotStable(a: NotStable) {
+              output.add("MemoNotStable")
+              Button(text="memo ${'$'}{a.value}")
+            }
+
+            @Composable
+            fun MemoModel(a: ValueHolder) {
+              output.add("MemoModelHolder")
+              Button(text="memo ${'$'}{a.value}")
+            }
+
+            @Composable
+            fun MemoEnum(a: EnumState) {
+              output.add("MemoEnum")
+              Button(text="memo ${'$'}{a}")
+            }
+
+            @Composable
+            fun MemoStable(a: StableClass) {
+              output.add("MemoStable")
+              Button(text="memo stable")
+            }
+
+            @Composable
+            fun MemoMutableState(a: MutableState<Int>) {
+              output.add("MemoMutableState")
+              Button(text="memo ${'$'}{a.value}")
+            }
+
+            @Composable
+            fun MemoState(a: State<Int>) {
+              output.add("MemoState")
+              Button(text="memo ${'$'}{a.value}")
+            }
+
+            @Composable
+            fun TestSkipping(
+                a: Int,
+                b: Float,
+                c: Double,
+                d: NotStable,
+                e: ValueHolder,
+                f: EnumState,
+                g: StableClass,
+                h: MutableState<Int>,
+                i: State<Int>
+            ) {
+              val am = a + m.value
+              output.add("TestSkipping a=${'$'}a am=${'$'}am")
+              MemoInt(a=am)
+              MemoFloat(a=b)
+              MemoDouble(a=c)
+              MemoNotStable(a=d)
+              MemoModel(a=e)
+              MemoEnum(a=f)
+              MemoStable(a=g)
+              MemoMutableState(h)
+              MemoState(i)
+            }
+
+            @Composable
+            fun Main(v: ValueHolder, n: NotStable) {
+              TestSkipping(
+                a=1,
+                b=1f,
+                c=2.0,
+                d=NotStable(),
+                e=v,
+                f=EnumState.One,
+                g=StableClass(),
+                h=mutableStateType,
+                i=stateType
+              )
+            }
+        """, """
+            output = outerOutput
+            val v = ValueHolder(0)
+            Main(v, NotStable())
+        """, {
+            mapOf(
+                "outerOutput: ArrayList<String>" to output
+            )
+        }).then {
+            // Expect that all the methods are called in order
+            assertEquals(
+                "TestSkipping a=1 am=1, MemoInt a=1, MemoFloat, " +
+                        "MemoDouble, MemoNotStable, MemoModelHolder, MemoEnum, MemoStable, " +
+                        "MemoMutableState, MemoState",
+                output.joinToString()
+            )
+            output.clear()
+        }.then { activity ->
+            // Expect TestSkipping and MemoNotStable to be called because the test forces an extra compose.
+            assertEquals("TestSkipping a=1 am=1, MemoNotStable", output.joinToString())
+            output.clear()
+
+            // Change the model
+            val button = activity.findViewById(101) as Button
+            button.performClick()
+        }.then {
+            // Expect that only MemoInt (the parameter changed) and MemoNotStable (it has unstable parameters) were
+            // called then expect a second compose which should only MemoNotStable
+            assertEquals(
+                "TestSkipping a=1 am=2, MemoInt a=2, MemoNotStable, " +
+                        "TestSkipping a=1 am=2, MemoNotStable",
+                output.joinToString()
+            )
+        }
+    }
+
+    @Test
+    fun testStableParameters_Lambdas(): Unit = ensureSetup {
+        val output = ArrayList<String>()
+        compose("""
+            val m = mutableStateOf(0)
+
+            var output = ArrayList<String>()
+            val unchanged: () -> Unit = { }
+
+            fun log(msg: String) { output.add(msg) }
+
+            @Composable
+            fun Container(children: @Composable () -> Unit) {
+              log("Container")
+              children()
+            }
+
+            @Composable
+            fun NormalLambda(index: Int, lambda: () -> Unit) {
+              log("NormalLambda(${'$'}index)")
+              Button(text="text")
+            }
+
+            @Composable
+            fun TestSkipping(unchanged: () -> Unit, changed: () -> Unit) {
+              log("TestSkipping")
+              Container {
+                NormalLambda(index = 1, lambda = unchanged)
+                NormalLambda(index = 2, lambda = unchanged)
+                NormalLambda(index = 3, lambda = unchanged)
+                NormalLambda(index = 4, lambda = changed)
+              }
+            }
+
+            fun forceNewLambda(): () -> Unit = { }
+
+            @Composable
+            fun Main(unchanged: () -> Unit) {
+              Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+              TestSkipping(unchanged = unchanged, changed = forceNewLambda())
+            }
+        """, """
+            output = outerOutput
+            Main(unchanged = unchanged)
+        """, {
+            mapOf(
+                "outerOutput: ArrayList<String>" to output
+            )
+        }).then {
+            // Expect that all the methods are called in order
+            assertEquals(
+                "TestSkipping, Container, NormalLambda(1), " +
+                        "NormalLambda(2), NormalLambda(3), NormalLambda(4)",
+                output.joinToString()
+            )
+            output.clear()
+        }.then { activity ->
+            // Expect nothing to occur with no changes
+            assertEquals("", output.joinToString())
+            output.clear()
+
+            // Change the model
+            val button = activity.findViewById(101) as Button
+            button.performClick()
+        }.then {
+            // Expect only NormalLambda(4) to be called
+            assertEquals(
+                "TestSkipping, NormalLambda(4)",
+                output.joinToString()
+            )
+        }
+    }
+
+    @Test
+    fun testRecomposeScope(): Unit = ensureSetup {
+        compose("""
+            val m = mutableStateOf(0)
+
+            @Composable
+            inline fun InlineContainer(children: @Composable () -> Unit) {
+                children()
+            }
+
+            @Composable
+            fun Container(children: @Composable () -> Unit) {
+                children()
+            }
+
+            @Composable
+            fun Leaf(v: Int) {}
+
+            @Composable
+            fun Inline() {
+                InlineContainer {
+                    Leaf(v = 1)
+                }
+            }
+
+            @Composable
+            fun Lambda() {
+                val a = 1
+                val b = 2
+                Container {
+                    TextView(text = "value = ${'$'}{m.value}", id = 100)
+                    Leaf(v = 1)
+                    Leaf(v = a)
+                    Leaf(v = b)
+                }
+            }
+            """,
+            """
+                Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+                Lambda()
+            """,
+            noParameters
+        ).then { activity ->
+            assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
+            val button = activity.findViewById<Button>(101)
+            button.performClick()
+        }.then { activity ->
+            assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
+        }
+    }
+
+    @Test
+    fun testRecomposeScope_ReceiverScope(): Unit = ensureSetup {
+        compose("""
+            val m = mutableStateOf(0)
+
+            class Receiver { var r: Int = 0 }
+
+            @Composable
+            fun Container(children: @Composable Receiver.() -> Unit) {
+                Receiver().children()
+            }
+
+            @Composable
+            fun Lambda() {
+                Container {
+                    TextView(text = "value = ${'$'}{m.value}", id = 100)
+                }
+            }
+            """,
+            """
+                Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+                Lambda()
+            """,
+            noParameters
+        ).then { activity ->
+            assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
+            val button = activity.findViewById<Button>(101)
+            button.performClick()
+        }.then { activity ->
+            assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
+        }
+    }
+
+    @Test
+    fun testRecomposeScope_Method(): Unit = ensureSetup {
+        compose("""
+            val m = mutableStateOf(0)
+
+            @Composable
+            fun Leaf() { }
+
+            class SelfCompose {
+                var f1 = 0
+
+                @Composable
+                fun compose(f2: Int) {
+                    TextView(
+                      text = "f1=${'$'}f1, f2=${'$'}f2, m=${'$'}{m.value*f1*f2}",
+                      id = 100
+                    )
+                }
+            }
+
+            @Composable
+            fun InvokeSelfCompose() {
+                val r = remember() { SelfCompose() }
+                r.f1 = 1
+                r.compose(f2 = 10)
+                Leaf()
+            }
+            """,
+            """
+                Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+                InvokeSelfCompose()
+            """,
+            noParameters
+        ).then { activity ->
+            assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=0")
+            val button = activity.findViewById<Button>(101)
+            button.performClick()
+        }.then { activity ->
+            assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=10")
+        }
     }
 }
 
+private val noParameters = { emptyMap<String, String>() }
+
 private inline fun <reified T : PsiElement> PsiElement.parentOfType(): T? = parentOfType(T::class)
 
 private fun <T : PsiElement> PsiElement.parentOfType(vararg classes: KClass<out T>): T? {
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolutionDiagnosticsTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolutionDiagnosticsTests.kt
deleted file mode 100644
index decde5b..0000000
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolutionDiagnosticsTests.kt
+++ /dev/null
@@ -1,78 +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.plugins.kotlin
-
-class ComposeCallResolutionDiagnosticsTests : AbstractComposeDiagnosticsTest() {
-
-    private var isSetup = false
-    override fun setUp() {
-        isSetup = true
-        super.setUp()
-    }
-
-    private fun <T> ensureSetup(block: () -> T): T {
-        if (!isSetup) setUp()
-        return block()
-    }
-
-    private fun setupAndDoTest(text: String) = ensureSetup { doTest(text) }
-
-    fun testImplicitlyPassedReceiverScope1() = setupAndDoTest(
-        """
-            import androidx.compose.*
-            import android.widget.*
-            import android.os.Bundle
-            import android.app.Activity
-            import android.widget.FrameLayout
-
-            val x: Any? = null
-
-            fun Activity.setViewContent(composable: @Composable () -> Unit): Composition? {
-                assert(composable != x)
-                return null
-            }
-
-            open class WebComponentActivity : Activity() {
-                override fun onCreate(savedInstanceState: Bundle?) {
-                    super.onCreate(savedInstanceState)
-
-                    setViewContent {
-                        FrameLayout {
-                        }
-                    }
-                }
-            }
-        """
-    )
-
-    fun testSimpleReceiverScope() = setupAndDoTest(
-        """
-            import android.widget.FrameLayout
-            import androidx.compose.Composable
-            import androidx.ui.node.UiComposer
-
-            class SomeScope {
-             val composer: UiComposer get() = error("should not be called")
-            }
-
-            @Composable fun SomeScope.foo() {
-                FrameLayout { }
-            }
-
-        """
-    )
-}
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt
index 32e6f2c..c27b941 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt
@@ -64,7 +64,6 @@
             @Composable
             fun test() {
                 <call>Foo()
-                <emit>TextView(text="text")
                 <normal>Bar()
             }
         """
@@ -198,12 +197,14 @@
             import androidx.compose.*
             import android.widget.LinearLayout
 
+            @Composable fun Group(content: @Composable () -> Unit) { content() }
+
             @Composable
             inline fun PointerInputWrapper(
                 crossinline children: @Composable () -> Unit
             ) {
                 // Hide the internals of PointerInputNode
-                <emit>LinearLayout {
+                <call>Group {
                     <call>children()
                 }
             }
@@ -231,15 +232,13 @@
                     "$calltype.")
 
             when (calltype) {
-                "<normal>" -> assert(!resolvedCall.isCall() && !resolvedCall.isEmit())
-                "<emit>" -> assert(resolvedCall.isEmit())
+                "<normal>" -> assert(!resolvedCall.isCall())
                 "<call>" -> assert(resolvedCall.isCall())
                 else -> error("Call type of $calltype not recognized.")
             }
         }
     }
 
-    private fun ResolvedCall<*>.isEmit(): Boolean = candidateDescriptor is ComposableEmitDescriptor
     private fun ResolvedCall<*>.isCall(): Boolean =
         when (candidateDescriptor) {
             is ComposableFunctionDescriptor -> true
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 b360a71..01f8b90 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
@@ -357,34 +357,6 @@
     )
 
     @Test
-    fun testSimpleEmits(): Unit = checkApi(
-        """
-            import android.widget.LinearLayout
-            import android.widget.TextView
-
-            @Composable fun Example() {
-                LinearLayout(id=123) {
-                    TextView(text="Hello World")
-                }
-            }
-        """,
-        """
-            public final class TestKt {
-              public final static Example(Landroidx/compose/Composer;II)V
-              final static INNERCLASS TestKt%Example%4 null null
-            }
-            final class TestKt%Example%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function3 {
-              <init>(I)V
-              public final invoke(Landroidx/compose/Composer;II)V
-              private final synthetic I %%changed
-              public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-              final static INNERCLASS TestKt%Example%4 null null
-              OUTERCLASS TestKt Example (Landroidx/compose/Composer;II)V
-            }
-        """
-    )
-
-    @Test
     fun testCorrectComposerPassed2(): Unit = checkComposerParam(
         """
             var a: Composer<*>? = null
@@ -475,21 +447,6 @@
     )
 
     @Test
-    fun testCorrectComposerPassed6(): Unit = checkComposerParam(
-        """
-            import android.widget.TextView
-
-            fun run() {
-                invokeComposable(makeComposer()) {
-                    LinearLayout(id=123) {
-                        TextView(text="Hello World")
-                    }
-                }
-            }
-        """
-    )
-
-    @Test
     fun testDefaultParameters(): Unit = checkApi(
         """
             @Composable fun Foo(x: Int = 0) {
@@ -935,33 +892,6 @@
     }
 
     @Test
-    fun testCustomComposerCall(): Unit = validateBytecode(
-        """
-        class VectorScope(val composer: VectorComposer)
-
-        @Composable fun VectorScope.Test(children: @Composable VectorScope.() -> Unit) {
-            children()
-        }
-
-        internal class AnyApplyAdapter : ApplyAdapter<Any> {
-            override fun Any.start(instance: Any) {}
-            override fun Any.insertAt(index: Int, instance: Any) {}
-            override fun Any.removeAt(index: Int, count: Int) {}
-            override fun Any.move(from: Int, to: Int, count: Int) {}
-            override fun Any.end(instance: Any, parent: Any) {}
-        }
-
-        class VectorComposer(
-            val root: Any,
-            slotTable: SlotTable,
-            recomposer: Recomposer
-        ) : Composer<Any>(slotTable, Applier(root, AnyApplyAdapter()), recomposer)
-        """
-    ) {
-        it.contains("INVOKEVIRTUAL androidx/compose/Composer.startGroup")
-    }
-
-    @Test
     fun testCallingProperties(): Unit = checkApi(
         """
             @Composable val bar: Int get() { return 123 }
@@ -1213,43 +1143,6 @@
     )
 
     @Test
-    fun testExtensionSetterEmit(): Unit = checkApi(
-        """
-            import android.widget.TextView
-
-            private fun TextView.setRef(ref: (TextView) -> Unit) {}
-
-            @Composable
-            fun Test() {
-                TextView(ref = {  })
-            }
-        """,
-        """
-            public final class TestKt {
-              private final static setRef(Landroid/widget/TextView;Lkotlin/jvm/functions/Function1;)V
-              public final static Test(Landroidx/compose/Composer;II)V
-              final static INNERCLASS TestKt%Test%1%1 null null
-              final static INNERCLASS TestKt%Test%4 null null
-            }
-            final class TestKt%Test%1%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function1 {
-              <init>()V
-              public final invoke(Landroid/widget/TextView;)V
-              public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
-              final static INNERCLASS TestKt%Test%1%1 null null
-              OUTERCLASS TestKt Test (Landroidx/compose/Composer;II)V
-            }
-            final class TestKt%Test%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function3 {
-              <init>(I)V
-              public final invoke(Landroidx/compose/Composer;II)V
-              private final synthetic I %%changed
-              public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-              final static INNERCLASS TestKt%Test%4 null null
-              OUTERCLASS TestKt Test (Landroidx/compose/Composer;II)V
-            }
-        """
-    )
-
-    @Test
     fun testDexNaming(): Unit = checkApi(
         """
             @Composable
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 2e2062f..d21dfc1 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
@@ -274,42 +274,6 @@
     )
 
     @Test
-    fun testExtensionSetterEmit(): Unit = composerParam(
-        """
-            import android.widget.TextView
-
-            private fun TextView.setRef(ref: (TextView) -> Unit) {}
-
-            @ComposableContract(restartable = false)
-            @Composable
-            fun Test() {
-                TextView(ref = {  })
-            }
-        """,
-        """
-            private fun TextView.setRef(ref: Function1<TextView, Unit>) { }
-            @ComposableContract(restartable = false)
-            @Composable
-            fun Test(%composer: Composer<*>?, %key: Int, %changed: Int) {
-              %composer.startReplaceableGroup(%key)
-              val tmp0 = remember({
-                { it: TextView ->
-                }
-              }, %composer, <>, 0)
-              %composer.emit(-1248659431, { context: @[ParameterName(name = 'context')] Context ->
-                TextView(context)
-              }
-              ) {
-                set(tmp0) { p0: Function1<TextView, Unit> ->
-                  setRef(p0)
-                }
-              }
-              %composer.endReplaceableGroup()
-            }
-        """
-    )
-
-    @Test
     fun testDexNaming(): Unit = composerParam(
         """
             @Composable
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 230cdc5..735a5ba 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
@@ -172,18 +172,22 @@
               %composer.startRestartGroup(%key)
               val %dirty = %changed
               val x = x
-              if (%default and 0b0001 === 0 && %changed and 0b0110 === 0) {
-                %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
+              if (%changed and 0b0110 === 0) {
+                %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
               }
               if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
                   %composer.startDefaults()
                   if (%default and 0b0001 !== 0) {
                     x = makeInt()
+                    %dirty = %dirty and 0b0110.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0001 !== 0) {
+                    %dirty = %dirty and 0b0110.inv()
+                  }
                 }
               } else {
                 %composer.skipToGroupEnd()
@@ -218,8 +222,8 @@
               } else if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
               }
-              if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
-                %dirty = %dirty or if (%composer.changed(b)) 0b00010000 else 0b1000
+              if (%changed and 0b00011000 === 0) {
+                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(b)) 0b00010000 else 0b1000
               }
               if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -229,10 +233,14 @@
                   }
                   if (%default and 0b0010 !== 0) {
                     b = a + 1
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
                 print(a)
                 print(b)
@@ -1207,6 +1215,7 @@
                   }
                   if (%default and 0b001000000000 !== 0) {
                     a09 = Foo()
+                    %dirty = %dirty and 0b000110000000000000000000.inv()
                   }
                   if (%default and 0b010000000000 !== 0) {
                     a10 = 0
@@ -1273,10 +1282,17 @@
                   }
                   if (%default1 and 0b0001 !== 0) {
                     a31 = Foo()
+                    %dirty2 = %dirty2 and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b001000000000 !== 0) {
+                    %dirty = %dirty and 0b000110000000000000000000.inv()
+                  }
+                  if (%default1 and 0b0001 !== 0) {
+                    %dirty2 = %dirty2 and 0b00011000.inv()
+                  }
                 }
                 print("Hello world!")
               } else {
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
deleted file mode 100644
index cacd00e..0000000
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt
+++ /dev/null
@@ -1,132 +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.compose.plugins.kotlin
-
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.annotation.Config
-
-@RunWith(ComposeRobolectricTestRunner::class)
-@Config(
-    manifest = Config.NONE,
-    minSdk = 23,
-    maxSdk = 23
-)
-class EmitTransformTests : AbstractIrTransformTest() {
-    @Before
-    fun before() {
-        setUp()
-    }
-    private fun emitTransform(
-        unchecked: String,
-        checked: String,
-        expectedTransformed: String,
-        dumpTree: Boolean = false
-    ) = verifyComposeIrTransform(
-        """
-            import androidx.compose.Composable
-            import androidx.compose.ComposableContract
-            import android.widget.TextView
-            import android.widget.LinearLayout
-
-            $checked
-        """.trimIndent(),
-        expectedTransformed,
-        """
-            import androidx.compose.Composable
-            import androidx.compose.ComposableContract
-            import android.widget.TextView
-            import android.widget.LinearLayout
-
-            $unchecked
-        """.trimIndent(),
-        dumpTree
-    )
-
-    @Test
-    fun testSimpleEmit2(): Unit = emitTransform(
-        """
-        """,
-        """
-            import androidx.compose.state
-            import androidx.compose.remember
-            import android.widget.Button
-
-            @Composable
-            fun App() {
-                val cond = state { true }
-                val text = if (cond.value) remember { "abc" } else remember { "def" }
-                Button(id=1, text=text, onClickListener={ cond.value = !cond.value })
-            }
-        """,
-        """
-            @Composable
-            fun App(%composer: Composer<*>?, %key: Int, %changed: Int) {
-              %composer.startRestartGroup(%key)
-              if (%changed !== 0 || !%composer.skipping) {
-                val cond = state(null, {
-                  val tmp0_return = true
-                  tmp0_return
-                }, %composer, <>, 0, 0b0001)
-                val text = if (cond.value) {
-                  %composer.startReplaceableGroup(<>)
-                  val tmp0_group = remember({
-                    val tmp0_return = "abc"
-                    tmp0_return
-                  }, %composer, <>, 0)
-                  %composer.endReplaceableGroup()
-                  tmp0_group
-                } else {
-                  %composer.startReplaceableGroup(<>)
-                  val tmp1_group = remember({
-                    val tmp0_return = "def"
-                    tmp0_return
-                  }, %composer, <>, 0)
-                  %composer.endReplaceableGroup()
-                  tmp1_group
-                }
-                val tmp0 = text
-                val tmp1 = remember(cond, {
-                  { it: View? ->
-                    cond.value = !cond.value
-                  }
-                }, %composer, <>, 0)
-                %composer.emit(1124847878, { context: @[ParameterName(name = 'context')] Context ->
-                  Button(context)
-                }
-                ) {
-                  set(1) { p0: Int ->
-                    setId(p0)
-                  }
-                  set(tmp0) { p0: CharSequence? ->
-                    setText(p0)
-                  }
-                  set(tmp1) { p0: Function1<View?, Unit>? ->
-                    setOnClickListener(p0)
-                  }
-                }
-              } else {
-                %composer.skipToGroupEnd()
-              }
-              %composer.endRestartGroup()?.updateScope { %composer: Composer<*>?, %key: Int, %force: Int ->
-                App(%composer, %key, %changed or 0b0001)
-              }
-            }
-        """
-    )
-}
\ No newline at end of file
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
deleted file mode 100644
index f09ae93..0000000
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
+++ /dev/null
@@ -1,2476 +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.
- */
-
-@file:Suppress("MemberVisibilityCanBePrivate")
-
-package androidx.compose.plugins.kotlin
-
-import android.view.View
-import android.widget.Button
-import android.widget.LinearLayout
-import android.widget.TextView
-import androidx.compose.Composer
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.RuntimeEnvironment
-import org.robolectric.annotation.Config
-import java.net.URLClassLoader
-
-private val noParameters = { emptyMap<String, String>() }
-
-@RunWith(ComposeRobolectricTestRunner::class)
-@Config(
-    manifest = Config.NONE,
-    minSdk = 23,
-    maxSdk = 23
-)
-class FcsCodegenTests : AbstractCodegenTest() {
-
-    @Test
-    fun testReturnValue(): Unit = ensureSetup {
-        compose("""
-            var a = 0
-            var b = 0
-
-            @Composable
-            fun SimpleComposable() {
-                a++
-                val c = state { 0 }
-                val d = remember(c.value) { b++; b }
-                val recompose = invalidate
-                Button(
-                  text=listOf(a, b, c.value, d).joinToString(", "),
-                  onClick={ c.value += 1 },
-                  id=42
-                )
-                Button(
-                  text="Recompose",
-                  onClick={ recompose() },
-                  id=43
-                )
-            }
-        """,
-            noParameters,
-            "SimpleComposable()"
-        ).then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals(
-                button.text,
-                listOf(
-                    1, // SimpleComposable has run once
-                    1, // memo has been called once because of initial mount
-                    0, // state was in itialized at 0
-                    1 // memo should return b
-                ).joinToString(", ")
-            )
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            val recompose = activity.findViewById(43) as Button
-            assertEquals(
-                button.text,
-                listOf(
-                    2, // SimpleComposable has run twice
-                    2, // memo has been called twice, because state input has changed
-                    1, // state was changed to 1
-                    2 // memo should return b
-                ).joinToString(", ")
-            )
-            recompose.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals(
-                button.text,
-                listOf(
-                    3, // SimpleComposable has run three times
-                    2, // memo was not called this time, because input didn't change
-                    1, // state stayed at 1
-                    2 // memo should return b
-                ).joinToString(", ")
-            )
-        }
-    }
-
-    @Test
-    fun testReorderedArgsReturnValue(): Unit = ensureSetup {
-        compose(
-            """
-            @Composable
-            fun SimpleComposable() {
-                val x = remember(calculation = { "abc" }, v1 = "def")
-                TextView(
-                  text=x,
-                  id=42
-                )
-            }
-        """,
-            noParameters,
-            "SimpleComposable()"
-        ).then { activity ->
-            val button = activity.findViewById(42) as TextView
-            assertEquals(button.text, "abc")
-        }
-    }
-
-    @Test
-    fun testTrivialReturnValue(): Unit = ensureSetup {
-        compose("""
-        @Composable
-        fun <T> identity(value: T): T = value
-
-        @Composable
-        fun SimpleComposable() {
-            val x = identity("def")
-            TextView(
-              text=x,
-              id=42
-            )
-        }
-    """,
-            noParameters,
-            "SimpleComposable()"
-        ).then { activity ->
-            val button = activity.findViewById(42) as TextView
-            assertEquals(button.text, "def")
-        }
-    }
-
-    @Test
-    fun testForDevelopment(): Unit = ensureSetup {
-        codegen(
-            """
-            import androidx.compose.*
-
-            @Composable
-            fun bar() {
-
-            }
-
-            @Composable
-            fun foo() {
-                TextView(text="Hello World")
-            }
-            """
-        )
-    }
-
-    @Test
-    fun testSimpleFunctionResolution(): Unit = ensureSetup {
-        compose(
-            """
-            import androidx.compose.*
-
-            @Composable
-            fun noise(text: String) {}
-
-            @Composable
-            fun bar() {
-                noise(text="Hello World")
-            }
-            """, noParameters,
-            """
-            """
-        )
-    }
-
-    @Test
-    fun testSimpleClassResolution(): Unit = ensureSetup {
-        compose(
-            """
-            import android.widget.TextView
-            import androidx.compose.*
-
-            @Composable
-            fun bar() {
-                TextView(text="Hello World")
-            }
-            """, noParameters,
-            """
-            """
-        )
-    }
-
-    @Test
-    fun testSetContent(): Unit = ensureSetup {
-        codegen(
-            """
-                fun fakeCompose(block: @Composable ()->Unit) { }
-
-                class Test {
-                    fun test() {
-                        fakeCompose {
-                            LinearLayout(orientation = LinearLayout.VERTICAL) {}
-                        }
-                    }
-                }
-            """
-        )
-    }
-
-    @Test
-    fun testComposeWithResult(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable fun <T> identity(block: @Composable ()->T): T = block()
-
-                @Composable
-                fun TestCall() {
-                  val value: Any = identity { 12 }
-                  TextView(text = value.toString(), id = 100)
-                }
-            """,
-            noParameters,
-            "TestCall()"
-        ).then { activity ->
-            val textView = activity.findViewById<TextView>(100)
-            assertEquals("12", textView.text)
-        }
-    }
-
-    @Test
-    fun testObservable(): Unit = ensureSetup {
-        compose(
-            """
-                import android.widget.Button
-                import androidx.compose.*
-                import androidx.ui.androidview.adapters.setOnClick
-
-                @Composable
-                fun SimpleComposable() {
-                    FancyButton(state=mutableStateOf(0))
-                }
-
-                @Composable
-                fun FancyButton(state: MutableState<Int>) {
-                    Button(text=("Clicked "+state.value+" times"), onClick={state.value++}, id=42)
-                }
-            """,
-            noParameters,
-            "SimpleComposable()"
-        ).then { activity ->
-            val button = activity.findViewById(42) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals("Clicked 3 times", button.text)
-        }
-    }
-
-    @Test
-    fun testObservableLambda(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun SimpleComposable(state: MutableState<Int>) {
-                    FancyBox2 {
-                        Button(
-                          text=("Button clicked "+state.value+" times"),
-                          onClick={state.value++},
-                          id=42
-                        )
-                    }
-                }
-
-                @Composable
-                fun FancyBox2(children: @Composable ()->Unit) {
-                    children()
-                }
-            """,
-            noParameters,
-            "SimpleComposable(state=state { 0 })"
-        ).then { activity ->
-            val button = activity.findViewById(42) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals("Button clicked 3 times", button.text)
-        }
-    }
-
-    @Test
-    fun testObservableGenericFunction(): Unit = ensureSetup {
-        compose("""
-            @Composable
-            fun <T> SimpleComposable(state: MutableState<Int>, value: T) {
-                Button(
-                  text=("Button clicked "+state.value+" times: " + value),
-                  onClick={state.value++},
-                  id=42
-                )
-            }
-        """,
-            noParameters,
-            "SimpleComposable(state=state { 0 }, value=\"Value\")"
-        ).then { activity ->
-            val button = activity.findViewById(42) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals("Button clicked 3 times: Value", button.text)
-        }
-    }
-
-    @Test
-    fun testObservableExtension(): Unit = ensureSetup {
-        compose("""
-
-            @Composable
-            fun MutableState<Int>.Composable() {
-                Button(
-                    text="Button clicked "+value+" times",
-                    onClick={value++},
-                    id=42
-                )
-            }
-
-            val myCounter = mutableStateOf(0)
-            """,
-            noParameters,
-            "myCounter.Composable()"
-        ).then { activity ->
-            val button = activity.findViewById<Button>(42)
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById<Button>(42)
-            assertEquals("Button clicked 3 times", button.text)
-        }
-    }
-
-    @Test
-    fun testObserverableExpressionBody(): Unit = ensureSetup {
-        compose("""
-            @Composable
-            fun SimpleComposable(counter: MutableState<Int>) =
-                Button(
-                    text="Button clicked "+counter.value+" times",
-                    onClick={counter.value++},
-                    id=42
-                )
-
-            @Composable
-            fun SimpleWrapper(counter: MutableState<Int>) = SimpleComposable(counter = counter)
-
-            val myCounter = mutableStateOf(0)
-            """,
-            noParameters,
-            "SimpleWrapper(counter = myCounter)"
-        ).then { activity ->
-            val button = activity.findViewById<Button>(42)
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById<Button>(42)
-            assertEquals("Button clicked 3 times", button.text)
-        }
-    }
-
-    @Test
-    fun testObservableInlineWrapper(): Unit = ensureSetup {
-        compose("""
-            var inWrapper = false
-            val counter = mutableStateOf(0)
-
-            inline fun wrapper(block: () -> Unit) {
-              inWrapper = true
-              try {
-                block()
-              } finally {
-                inWrapper = false
-              }
-            }
-
-            @Composable
-            fun SimpleComposable(state: MutableState<Int>) {
-                wrapper {
-                    Button(
-                      text=("Button clicked "+state.value+" times"),
-                      onClick={state.value++},
-                      id=42
-                    )
-                }
-            }
-        """,
-            noParameters,
-            "SimpleComposable(state=counter)"
-        ).then { activity ->
-            val button = activity.findViewById(42) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals("Button clicked 3 times", button.text)
-        }
-    }
-
-    @Test
-    fun testObservableDefaultParameter(): Unit = ensureSetup {
-        compose("""
-            val counter = mutableStateOf(0)
-
-            @Composable
-            fun SimpleComposable(state: MutableState<Int>, a: Int = 1, b: Int = 2) {
-                Button(
-                  text=("State: ${'$'}{state.value} a = ${'$'}a b = ${'$'}b"),
-                  onClick={state.value++},
-                  id=42
-                )
-            }
-        """,
-            noParameters,
-            "SimpleComposable(state=counter, b = 4)"
-        ).then { activity ->
-            val button = activity.findViewById(42) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById(42) as Button
-            assertEquals("State: 3 a = 1 b = 4", button.text)
-        }
-    }
-
-    @Test
-    fun testObservableEarlyReturn(): Unit = ensureSetup {
-        compose("""
-
-            val counter = mutableStateOf(0)
-
-            @Composable
-            fun SimpleComposable(state: MutableState<Int>) {
-                Button(
-                  text=("State: ${'$'}{state.value}"),
-                  onClick={state.value++},
-                  id=42
-                )
-
-                if (state.value > 2) return
-
-                TextView(
-                  text="Included text",
-                  id=43
-                )
-            }
-        """,
-            noParameters,
-            "SimpleComposable(state=counter)"
-        ).then { activity ->
-            // Check that the text view is in the view
-            assertNotNull(activity.findViewById(43))
-            val button = activity.findViewById(42) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            val button = activity.findViewById<Button>(42)
-            assertEquals("State: 3", button.text)
-
-            // Assert that the text view is no longer in the view
-            assertNull(activity.findViewById<Button>(43))
-        }
-    }
-
-    @Test
-    fun testCGSimpleTextView(): Unit = ensureSetup {
-        compose(
-            """
-                TextView(text="Hello, world!", id=42)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGLocallyScopedFunction(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo() {
-                    @Composable fun Bar() {
-                        TextView(text="Hello, world!", id=42)
-                    }
-                    Bar()
-                }
-            """,
-            noParameters,
-            """
-                Foo()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGLocallyScopedExtensionFunction(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(x: String) {
-                    @Composable fun String.Bar() {
-                        TextView(text=this, id=42)
-                    }
-                    x.Bar()
-                }
-            """,
-            noParameters,
-            """
-                Foo(x="Hello, world!")
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testImplicitReceiverScopeCall(): Unit = ensureSetup {
-        compose(
-            """
-                import androidx.compose.*
-
-                class Bar(val text: String)
-
-                @Composable fun Bar.Foo() {
-                    TextView(text=text,id=42)
-                }
-
-                @Composable
-                fun Bam(bar: Bar) {
-                    with(bar) {
-                        Foo()
-                    }
-                }
-            """,
-            noParameters,
-            """
-                Bam(bar=Bar("Hello, world!"))
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGLocallyScopedInvokeOperator(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(x: String) {
-                    @Composable
-                    operator fun String.invoke() {
-                        TextView(text=this, id=42)
-                    }
-                    x()
-                }
-            """,
-            noParameters,
-            """
-                Foo(x="Hello, world!")
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testTrivialExtensionFunction(): Unit = ensureSetup {
-        compose(
-            """ """,
-            { mapOf<String, String>() },
-            """
-                val x = "Hello"
-                @Composable fun String.foo() {}
-                x.foo()
-            """
-        )
-    }
-
-    @Test
-    fun testTrivialInvokeExtensionFunction(): Unit = ensureSetup {
-        compose(
-            """ """,
-            noParameters,
-            """
-                val x = "Hello"
-                @Composable operator fun String.invoke() {}
-                x()
-            """
-        )
-    }
-
-    @Test
-    fun testCGNSimpleTextView(): Unit = ensureSetup {
-        compose(
-            """
-                TextView(text="Hello, world!", id=42)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testInliningTemp(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(x: Double, children: @Composable Double.() -> Unit) {
-                  x.children()
-                }
-            """,
-            { mapOf("foo" to "bar") },
-            """
-                Foo(x=1.0) {
-                    TextView(text=this.toString(), id=123)
-                }
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(123) as TextView
-            assertEquals("1.0", textView.text)
-        }
-    }
-
-    @Test
-    fun testInliningTemp2(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(onClick: Double.() -> Unit) {
-
-                }
-            """,
-            { mapOf("foo" to "bar") },
-            """
-                Foo(onClick={})
-            """
-        ).then { }
-    }
-
-    @Test
-    fun testInliningTemp3(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(onClick: (Double) -> Unit) {
-
-                }
-            """,
-            { mapOf("foo" to "bar") },
-            """
-                Foo(onClick={})
-            """
-        ).then { }
-    }
-
-    @Test
-    fun testInliningTemp4(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(onClick: (Double) -> Unit) {
-
-                }
-            """,
-            { mapOf("foo" to "bar") },
-            """
-                Foo(onClick={})
-            """
-        ).then {}
-    }
-
-    @Test
-    fun testInline_NonComposable_Identity(): Unit = ensureSetup {
-        compose("""
-            @Composable inline fun InlineWrapper(base: Int, children: @Composable ()->Unit) {
-              children()
-            }
-            """,
-            noParameters,
-            """
-            InlineWrapper(200) {
-              TextView(text = "Test", id=101)
-            }
-            """).then { activity ->
-            assertEquals("Test", activity.findViewById<TextView>(101).text)
-        }
-    }
-
-    @Test
-    fun testInline_Composable_Identity(): Unit = ensureSetup {
-        compose("""
-            @Composable
-            inline fun InlineWrapper(base: Int, children: @Composable ()->Unit) {
-              children()
-            }
-            """,
-            noParameters,
-            """
-            InlineWrapper(200) {
-                TextView(text = "Test", id=101)
-            }
-            """).then { activity ->
-            assertEquals("Test", activity.findViewById<TextView>(101).text)
-        }
-    }
-
-    @Test
-    fun testInline_Composable_EmitChildren(): Unit = ensureSetup {
-        compose("""
-            @Composable
-            inline fun InlineWrapper(base: Int, crossinline children: @Composable ()->Unit) {
-              LinearLayout(id = base + 0) {
-                children()
-              }
-            }
-            """,
-            noParameters,
-            """
-            InlineWrapper(200) {
-              TextView(text = "Test", id=101)
-            }
-            """).then { activity ->
-            val tv = activity.findViewById<TextView>(101)
-            // Assert the TextView was created with the correct text
-            assertEquals("Test", tv.text)
-            // and it is the first child of the linear layout
-            assertEquals(tv, activity.findViewById<LinearLayout>(200).getChildAt(0))
-        }
-    }
-
-    @Test
-    fun testCGNInlining(): Unit = ensureSetup {
-        compose(
-            """
-                LinearLayout(orientation=LinearLayout.VERTICAL) {
-                    TextView(text="Hello, world!", id=42)
-                }
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGUpdatedComposition(): Unit = ensureSetup {
-        var value = "Hello, world!"
-
-        compose(
-            { mapOf("value" to value) }, """
-           TextView(text=value, id=42)
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-
-            value = "Other value"
-        }.then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Other value", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGNUpdatedComposition(): Unit = ensureSetup {
-        var value = "Hello, world!"
-
-        compose(
-            { mapOf("value" to value) }, """
-           TextView(text=value, id=42)
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-
-            value = "Other value"
-        }.then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Other value", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGViewGroup(): Unit = ensureSetup {
-        val tvId = 258
-        val llId = 260
-        var text = "Hello, world!"
-        var orientation = LinearLayout.HORIZONTAL
-
-        compose(
-            { mapOf("text" to text, "orientation" to orientation) }, """
-            LinearLayout(orientation=orientation, id=$llId) {
-              TextView(text=text, id=$tvId)
-            }
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val linearLayout = activity.findViewById(llId) as LinearLayout
-
-            assertEquals(text, textView.text)
-            assertEquals(orientation, linearLayout.orientation)
-
-            text = "Other value"
-            orientation = LinearLayout.VERTICAL
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val linearLayout = activity.findViewById(llId) as LinearLayout
-
-            assertEquals(text, textView.text)
-            assertEquals(orientation, linearLayout.orientation)
-        }
-    }
-
-    // @Test
-    fun testCGNAmbient(): Unit = ensureSetup {
-        val tvId = 258
-        var text = "Hello, world!"
-
-        compose(
-            """
-
-            val StringAmbient = ambientOf<String> { "default" }
-
-            @Composable fun Foo() {
-                TextView(id=$tvId, text=StringAmbient.current)
-            }
-
-        """,
-            { mapOf("text" to text) },
-            """
-            Providers(StringAmbient provides text) {
-                Foo()
-            }
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-            text = "wat"
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-        }
-    }
-
-    @Test
-    fun testCGNFunctionComponent(): Unit = ensureSetup {
-        var text = "Hello, world!"
-        val tvId = 123
-
-        compose(
-            """
-            @Composable
-            fun Foo(text: String) {
-                TextView(id=$tvId, text=text)
-            }
-
-        """,
-            { mapOf("text" to text) },
-            """
-             Foo(text=text)
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-            text = "wat"
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-        }
-    }
-
-    // @Test
-    fun testAmbientReference(): Unit = ensureSetup {
-        val outerId = 123
-        val innerId = 345
-        val buttonId = 456
-
-        compose(
-            """
-                fun buildPortal() = effectOf<Ambient.Reference> {
-                    context.buildReference()
-                }
-
-                fun <T> refFor() = memo { Ref<T>() }
-
-                val textAmbient = Ambient.of { "default" }
-
-                @Composable fun DisplayTest(id: Int) {
-                    val text = ambient(textAmbient)
-                    TextView(id=id, text=text)
-                }
-
-                @Composable fun PortalTest() {
-                    val portal = +buildPortal()
-                    val ref = +refFor<LinearLayout>()
-                    DisplayTest(id=$outerId)
-
-                    LinearLayout(ref=ref)
-
-                    val root = ref.value ?: error("Expected a linear")
-
-                    composeInto(root, portal) {
-                        DisplayTest(id=$innerId)
-                    }
-                }
-
-                @Composable
-                fun TestApp() {
-                    val inc = state { 1 }
-
-                    Button(id=$buttonId, text="Click Me", onClick={ inc.value += 1 })
-
-                    textAmbient.Provider(value="value: ${"$"}{inc.value}") {
-                        PortalTest()
-                    }
-                }
-            """,
-            { mapOf("text" to "") },
-            """
-                TestApp()
-            """
-        ).then { activity ->
-            val inner = activity.findViewById(innerId) as TextView
-            val outer = activity.findViewById(outerId) as TextView
-            val button = activity.findViewById(buttonId) as Button
-
-            assertEquals("inner", "value: 1", inner.text)
-            assertEquals("outer", "value: 1", outer.text)
-
-            button.performClick()
-        }.then { activity ->
-            val inner = activity.findViewById(innerId) as TextView
-            val outer = activity.findViewById(outerId) as TextView
-            val button = activity.findViewById(buttonId) as Button
-
-            assertEquals("inner", "value: 2", inner.text)
-            assertEquals("outer", "value: 2", outer.text)
-
-            button.performClick()
-        }.then { activity ->
-            val inner = activity.findViewById(innerId) as TextView
-            val outer = activity.findViewById(outerId) as TextView
-
-            assertEquals("inner", "value: 3", inner.text)
-            assertEquals("outer", "value: 3", outer.text)
-        }
-    }
-
-    @Test
-    fun testAmbientConsumedFromDefaultParameter(): Unit = ensureSetup {
-        val initialText = "no text"
-        val helloWorld = "Hello World!"
-        compose("""
-            val TextAmbient = ambientOf { "$initialText" }
-
-            @Composable
-            fun Main() {
-                var text = state { "$initialText" }
-                Providers(TextAmbient provides text.value) {
-                    LinearLayout {
-                        ConsumesAmbientFromDefaultParameter()
-                        Button(
-                            text = "Change ambient value",
-                            onClick={ text.value = "$helloWorld" },
-                            id=101
-                        )
-                    }
-                }
-            }
-
-            @Composable
-            fun ConsumesAmbientFromDefaultParameter(text: String = TextAmbient.current) {
-                TextView(text = text, id = 42)
-            }
-        """,
-            noParameters,
-            "Main()"
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals(initialText, textView.text)
-        }.then { activity ->
-            val button = activity.findViewById(101) as Button
-            button.performClick()
-        }
-        .then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals(helloWorld, textView.text)
-        }
-    }
-
-    @Test
-    fun testCGNViewGroup(): Unit = ensureSetup {
-        val tvId = 258
-        val llId = 260
-        var text = "Hello, world!"
-        var orientation = LinearLayout.HORIZONTAL
-
-        compose(
-            { mapOf("text" to text, "orientation" to orientation) }, """
-             LinearLayout(orientation=orientation, id=$llId) {
-               TextView(text=text, id=$tvId)
-             }
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val linearLayout = activity.findViewById(llId) as LinearLayout
-
-            assertEquals(text, textView.text)
-            assertEquals(orientation, linearLayout.orientation)
-
-            text = "Other value"
-            orientation = LinearLayout.VERTICAL
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val linearLayout = activity.findViewById(llId) as LinearLayout
-
-            assertEquals(text, textView.text)
-            assertEquals(orientation, linearLayout.orientation)
-        }
-    }
-
-    @Test
-    fun testMemoization(): Unit = ensureSetup {
-        val tvId = 258
-        val tagId = (3 shl 24) or "composed_set".hashCode()
-
-        compose(
-            """
-                var composedSet = mutableSetOf<String>()
-                var inc = 1
-
-                fun View.setComposed(composed: Set<String>) = setTag($tagId, composed)
-
-                @Composable fun ComposePrimitive(value: Int) {
-                    composedSet.add("ComposePrimitive(" + value + ")")
-                }
-
-                class MutableThing(var value: String)
-
-                val constantMutableThing = MutableThing("const")
-
-                @Composable fun ComposeMutable(value: MutableThing) {
-                    composedSet.add("ComposeMutable(" + value.value + ")")
-                }
-            """,
-            { mapOf("text" to "") },
-            """
-                composedSet.clear()
-
-                ComposePrimitive(value=123)
-                ComposePrimitive(value=inc)
-                ComposeMutable(value=constantMutableThing)
-                ComposeMutable(value=MutableThing("new"))
-
-                TextView(id=$tvId, composed=composedSet)
-
-                inc++
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val composedSet = textView.getComposedSet(tagId) ?: error(
-                "expected a compose set to exist")
-
-            fun assertContains(contains: Boolean, key: String) {
-                assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
-            }
-
-            assertContains(true, "ComposePrimitive(123)")
-            assertContains(true, "ComposePrimitive(1)")
-            assertContains(true, "ComposeMutable(const)")
-            assertContains(true, "ComposeMutable(new)")
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val composedSet = textView.getComposedSet(tagId)
-                ?: error("expected a compose set to exist")
-
-            fun assertContains(contains: Boolean, key: String) {
-                assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
-            }
-
-            // the primitive component skips based on equality
-            assertContains(false, "ComposePrimitive(123)")
-
-            // since the primitive changed, this one recomposes again
-            assertContains(true, "ComposePrimitive(2)")
-
-            // since this is a potentially mutable object, we don't skip based on it
-            assertContains(true, "ComposeMutable(const)")
-
-            // since its a new one every time, we definitely don't skip
-            assertContains(true, "ComposeMutable(new)")
-        }
-    }
-
-    @Test
-    fun testInlineClassMemoization(): Unit = ensureSetup {
-        val tvId = 258
-        val tagId = (3 shl 24) or "composed_set".hashCode()
-
-        compose(
-            """
-                inline class InlineInt(val value: Int)
-                inline class InlineInlineInt(val value: InlineInt)
-                inline class InlineMutableSet(val value: MutableSet<String>)
-                fun View.setComposed(composed: Set<String>) = setTag($tagId, composed)
-
-                val composedSet = mutableSetOf<String>()
-                val constInlineInt = InlineInt(0)
-                var inc = 2
-                val constInlineMutableSet = InlineMutableSet(mutableSetOf("a"))
-
-                @Composable fun ComposedInlineInt(value: InlineInt) {
-                  composedSet.add("ComposedInlineInt(" + value + ")")
-                }
-
-                @Composable fun ComposedInlineInlineInt(value: InlineInlineInt) {
-                  composedSet.add("ComposedInlineInlineInt(" + value + ")")
-                }
-
-                @Composable fun ComposedInlineMutableSet(value: InlineMutableSet) {
-                  composedSet.add("ComposedInlineMutableSet(" + value + ")")
-                }
-            """,
-            { mapOf("text" to "") },
-            """
-                composedSet.clear()
-
-                ComposedInlineInt(constInlineInt)
-                ComposedInlineInt(InlineInt(1))
-                ComposedInlineInt(InlineInt(inc))
-                ComposedInlineInlineInt(InlineInlineInt(InlineInt(2)))
-                ComposedInlineMutableSet(constInlineMutableSet)
-
-                TextView(id=$tvId, composed=composedSet)
-
-                inc++
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val composedSet = textView.getComposedSet(tagId)
-                ?: error("expected a compose set to exist")
-
-            // All composables should execute since it's the first time.
-            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
-            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
-            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=2))"))
-            assert(composedSet.contains(
-                "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
-            assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val composedSet = textView.getComposedSet(tagId)
-                ?: error("expected a compose set to exist")
-
-            // InlineInt and InlineInlineInt are stable, so the corresponding composables should
-            // not run for values equal to previous compositions.
-            assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
-            assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
-            assert(!composedSet.contains(
-                "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
-
-            // But if a stable composable is passed a new value, it should re-run.
-            assert(composedSet.contains("ComposedInlineInt(InlineInt(value=3))"))
-
-            // And composables for inline classes with non-stable underlying types should run.
-            assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
-        }
-    }
-
-    @Test
-    fun testStringParameterMemoization(): Unit = ensureSetup {
-        val tvId = 258
-        val tagId = (3 shl 24) or "composed_set".hashCode()
-
-        compose(
-            """
-                fun View.setComposed(composed: Set<String>) = setTag($tagId, composed)
-
-                val composedSet = mutableSetOf<String>()
-                val FOO = "foo"
-
-                @Composable fun ComposedString(value: String) {
-                  composedSet.add("ComposedString(" + value + ")")
-                }
-            """,
-            { mapOf("text" to "") },
-            """
-                composedSet.clear()
-
-                ComposedString(FOO)
-                ComposedString("bar")
-
-                TextView(id=$tvId, composed=composedSet)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val composedSet = textView.getComposedSet(tagId)
-                ?: error("expected a compose set to exist")
-
-            // All composables should execute since it's the first time.
-            assert(composedSet.contains("ComposedString(foo)"))
-            assert(composedSet.contains("ComposedString(bar)"))
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            val composedSet = textView.getComposedSet(tagId)
-                ?: error("expected a compose set to exist")
-
-            assert(composedSet.isEmpty())
-        }
-    }
-
-    @Test
-    fun testCGNSimpleCall(): Unit = ensureSetup {
-        val tvId = 258
-        var text = "Hello, world!"
-
-        compose(
-            """
-                @Composable fun SomeFun(x: String) {
-                    TextView(text=x, id=$tvId)
-                }
-            """,
-            { mapOf("text" to text) },
-            """
-                SomeFun(x=text)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-
-            text = "Other value"
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-        }
-    }
-
-    // @Test
-    fun testCGNSimpleCall2(): Unit = ensureSetup {
-        val tvId = 258
-        var text = "Hello, world!"
-        var someInt = 456
-
-        compose(
-            """
-                class SomeClass(var x: String) {
-                    @Composable
-                    operator fun invoke(y: Int) {
-                        TextView(text="${"$"}x ${"$"}y", id=$tvId)
-                    }
-                }
-            """,
-            { mapOf("text" to text, "someInt" to someInt) },
-            """
-                SomeClass(x=text, y=someInt)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals("Hello, world! 456", textView.text)
-
-            text = "Other value"
-            someInt = 123
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals("Other value 123", textView.text)
-        }
-    }
-
-    @Test
-    fun testCGNCallWithChildren(): Unit = ensureSetup {
-        val tvId = 258
-        var text = "Hello, world!"
-
-        compose(
-            """
-                @Composable
-                fun Block(children: @Composable () -> Unit) {
-                    children()
-                }
-            """,
-            { mapOf("text" to text) },
-            """
-                Block {
-                    Block {
-                        TextView(text=text, id=$tvId)
-                    }
-                }
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-
-            text = "Other value"
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-
-            assertEquals(text, textView.text)
-        }
-    }
-
-    // @Test
-    fun testCGNStuff(): Unit = ensureSetup {
-        val tvId = 258
-        var num = 123
-
-        compose(
-            """
-                class OneArg {
-                    var foo = 0
-                    @Composable
-                    operator fun invoke() {
-                        TextView(text="${"$"}foo", id=$tvId)
-                    }
-                }
-                fun OneArg.setBar(bar: Int) { foo = bar }
-            """,
-            { mapOf("num" to num) },
-            """
-            OneArg(bar=num)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            assertEquals("$num", textView.text)
-
-            num = 456
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            assertEquals("$num", textView.text)
-        }
-    }
-
-    // @Test
-    fun testTagBasedMemoization(): Unit = ensureSetup {
-        val tvId = 258
-        var text = "Hello World"
-
-        compose(
-            """
-                class A {
-                    var foo = ""
-                    inner class B {
-                        @Composable
-                        operator fun invoke() {
-                            TextView(text=foo, id=$tvId)
-                        }
-                    }
-                }
-            """,
-            { mapOf("text" to text) },
-            """
-                val a = A()
-                a.foo = text
-                a.B()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            assertEquals(text, textView.text)
-
-            text = "new value"
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            assertEquals(text, textView.text)
-        }
-    }
-
-    @Test
-    fun testCGComposableFunctionInvocationOneParameter(): Unit = ensureSetup {
-        val tvId = 91
-        var phone = "(123) 456-7890"
-        compose(
-            """
-           @Composable
-           fun Phone(value: String) {
-             TextView(text=value, id=$tvId)
-           }
-        """, { mapOf("phone" to phone) }, """
-           Phone(value=phone)
-        """
-        ).then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            assertEquals(phone, textView.text)
-
-            phone = "(123) 456-7899"
-        }.then { activity ->
-            val textView = activity.findViewById(tvId) as TextView
-            assertEquals(phone, textView.text)
-        }
-    }
-
-    @Test
-    fun testCGComposableFunctionInvocationTwoParameters(): Unit = ensureSetup {
-        val tvId = 111
-        val rsId = 112
-        var left = 0
-        var right = 0
-        compose(
-            """
-           var addCalled = 0
-
-           @Composable
-           fun AddView(left: Int, right: Int) {
-             addCalled++
-             TextView(text="${'$'}left + ${'$'}right = ${'$'}{left + right}", id=$tvId)
-             TextView(text="${'$'}addCalled", id=$rsId)
-           }
-        """, { mapOf("left" to left, "right" to right) }, """
-           AddView(left=left, right=right)
-        """
-        ).then { activity ->
-            // Should be called on the first compose
-            assertEquals("1", (activity.findViewById(rsId) as TextView).text)
-            assertEquals(
-                "$left + $right = ${left + right}",
-                (activity.findViewById(tvId) as TextView).text
-            )
-        }.then { activity ->
-            // Should be skipped on the second compose
-            assertEquals("1", (activity.findViewById(rsId) as TextView).text)
-            assertEquals(
-                "$left + $right = ${left + right}",
-                (activity.findViewById(tvId) as TextView).text
-            )
-
-            left = 1
-        }.then { activity ->
-            // Should be called again because left changed.
-            assertEquals("2", (activity.findViewById(rsId) as TextView).text)
-            assertEquals(
-                "$left + $right = ${left + right}",
-                (activity.findViewById(tvId) as TextView).text
-            )
-
-            right = 41
-        }.then { activity ->
-            // Should be called again because right changed
-            assertEquals("3", (activity.findViewById(rsId) as TextView).text)
-            assertEquals(
-                "$left + $right = ${left + right}",
-                (activity.findViewById(tvId) as TextView).text
-            )
-        }.then { activity ->
-            // Should be skipped because nothing changed
-            assertEquals("3", (activity.findViewById(rsId) as TextView).text)
-        }
-    }
-
-    @Test
-    fun testImplicitReceiverPassing1(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable fun Int.Foo(x: @Composable Int.() -> Unit) {
-                    x()
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                val id = 42
-
-                id.Foo(x={
-                    TextView(text="Hello, world!", id=this)
-                })
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testImplicitReceiverPassing2(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable fun Int.Foo(x: @Composable Int.(text: String) -> Unit, text: String) {
-                    x(text=text)
-                }
-
-                @Composable fun MyText(text: String, id: Int) {
-                    TextView(text=text, id=id)
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                val id = 42
-
-                id.Foo(text="Hello, world!", x={ text ->
-                    MyText(text=text, id=this)
-                })
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testEffects1(): Unit = ensureSetup {
-        compose(
-            """
-                import androidx.ui.androidview.adapters.*
-
-                @Composable
-                fun Counter() {
-                    var count = state { 0 }
-                    TextView(
-                        text=("Count: " + count.value),
-                        onClick={
-                            count.value += 1
-                        },
-                        id=42
-                    )
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                Counter()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Count: 0", textView.text)
-            textView.performClick()
-        }.then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Count: 1", textView.text)
-        }
-    }
-
-    @Test
-    fun testEffects2(): Unit = ensureSetup {
-        compose(
-            """
-                import androidx.ui.androidview.adapters.*
-
-                @Composable
-                fun Counter() {
-                    var count = state { 0 }
-                    TextView(
-                        text=("Count: " + count.value),
-                        onClick={
-                            count.value += 1
-                        },
-                        id=42
-                    )
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                Counter()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Count: 0", textView.text)
-            textView.performClick()
-        }.then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Count: 1", textView.text)
-        }
-    }
-
-    @Test
-    fun testEffects3(): Unit = ensureSetup {
-        val log = StringBuilder()
-        compose(
-            """
-                import androidx.ui.androidview.adapters.*
-
-                @Composable
-                fun Counter(log: StringBuilder) {
-                    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) },
-            """
-                Counter(log=log)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Count: 0", textView.text)
-            assertEquals("ab", log.toString())
-
-            execute {
-                textView.performClick()
-            }
-
-            assertEquals("Count: 1", textView.text)
-            assertEquals("aba", log.toString())
-        }
-    }
-
-    @Test
-    fun testEffects4(): Unit = ensureSetup {
-        val log = StringBuilder()
-        compose(
-            """
-                import androidx.ui.androidview.adapters.*
-
-                @Composable
-                fun printer(log: StringBuilder, str: String) {
-                    onCommit {
-                        log.append(str)
-                    }
-                }
-
-                @Composable
-                fun Counter(log: StringBuilder) {
-                    var count = state { 0 }
-                    printer(log, "" + count.value)
-                    TextView(
-                        text=("Count: " + count.value),
-                        onClick={
-                            count.value += 1
-                        },
-                        id=42
-                    )
-                }
-            """,
-            { mapOf("log" to log) },
-            """
-                Counter(log=log)
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Count: 0", textView.text)
-            assertEquals("0", log.toString())
-
-            execute {
-                textView.performClick()
-            }
-
-            assertEquals("Count: 1", textView.text)
-            assertEquals("01", log.toString())
-        }
-    }
-
-    @Test
-    fun testVariableCalls1(): Unit = ensureSetup {
-        compose(
-            """
-                val component = @Composable {
-                    TextView(text="Hello, world!", id=42)
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                component()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testVariableCalls2(): Unit = ensureSetup {
-        compose(
-            """
-                val component = @Composable {
-                    TextView(text="Hello, world!", id=42)
-                }
-                class HolderA(val composable: @Composable () -> Unit)
-
-                val holder = HolderA(component)
-
-            """,
-            { mapOf<String, String>() },
-            """
-                holder.composable()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testVariableCalls3(): Unit = ensureSetup {
-        compose(
-            """
-                val component = @Composable {
-                    TextView(text="Hello, world!", id=42)
-                }
-                class HolderB(val composable: @Composable () -> Unit) {
-                    @Composable
-                    fun Foo() {
-                        composable()
-                    }
-                }
-
-                val holder = HolderB(component)
-
-            """,
-            { mapOf<String, String>() },
-            """
-                holder.Foo()
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    // b/123721921
-    @Test
-    fun testDefaultParameters1(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(a: Int = 42, b: String) {
-                    TextView(text=b, id=a)
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                Foo(b="Hello, world!")
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testDefaultParameters2(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun Foo(a: Int = 42, b: String, c: @Composable () -> Unit) {
-                    c()
-                    TextView(text=b, id=a)
-                }
-            """,
-            { mapOf<String, String>() },
-            """
-                Foo(b="Hello, world!") {}
-            """
-        ).then { activity ->
-            val textView = activity.findViewById(42) as TextView
-            assertEquals("Hello, world!", textView.text)
-        }
-    }
-
-    @Test
-    fun testMovement(): Unit = ensureSetup {
-        val tvId = 50
-        val btnIdAdd = 100
-        val btnIdUp = 200
-        val btnIdDown = 300
-
-        // Duplicate the steps to reproduce an issue discovered in the Reorder example
-        compose(
-            """
-            fun <T> List<T>.move(from: Int, to: Int): List<T> {
-                if (to < from) return move(to, from)
-                val item = get(from)
-                val currentItem = get(to)
-                val left = if (from > 0) subList(0, from) else emptyList()
-                val right = if (to < size) subList(to + 1, size) else emptyList()
-                val middle = if (to - from > 1) subList(from + 1, to) else emptyList()
-                return left + listOf(currentItem) + middle + listOf(item) + right
-            }
-
-            @Composable
-            fun Reordering() {
-                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)
-                                    }
-                                }
-                            )
-                        }
-                    }
-                }
-            }
-
-            @Composable
-            // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
-            fun Item(id: Int, onMove: (Int) -> Unit) {
-                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,
-            """
-               Reordering()
-            """
-        ).then { activity ->
-            // Click 5 add
-            val button = activity.findViewById(btnIdAdd + 5) as Button
-            button.performClick()
-        }.then { activity ->
-            // Click 5 down
-            val button = activity.findViewById(btnIdDown + 5) as Button
-            button.performClick()
-        }.then { activity ->
-            // Click 5 down
-            val button = activity.findViewById(btnIdDown + 5) as Button
-            button.performClick()
-        }.then { activity ->
-            // Click 5 up
-            val button = activity.findViewById(btnIdUp + 5) as Button
-            button.performClick()
-        }.then { activity ->
-            // Click 5 up
-            val button = activity.findViewById(btnIdUp + 5) as Button
-            button.performClick()
-        }.then { activity ->
-            // Click 5 add
-            val button = activity.findViewById(btnIdAdd + 5) as Button
-            button.performClick()
-        }.then { activity ->
-            val textView = activity.findViewById(tvId + 5) as TextView
-            assertEquals("id: 5 amt: 2", textView.text)
-        }
-    }
-
-    @Test
-    fun testObserveKtxWithInline(): Unit = ensureSetup {
-        compose(
-            """
-                @Composable
-                fun SimpleComposable() {
-                    val count = state { 1 }
-                    Box {
-                        repeat(count.value) {
-                            Button(text="Increment", onClick={ count.value += 1 }, id=(41+it))
-                        }
-                    }
-                }
-
-                @Composable
-                fun Box(children: @Composable ()->Unit) {
-                    LinearLayout(orientation=LinearLayout.VERTICAL) {
-                        children()
-                    }
-                }
-            """, noParameters,
-            """
-               SimpleComposable()
-            """
-        ).then { activity ->
-            val button = activity.findViewById(41) as Button
-            button.performClick()
-            button.performClick()
-            button.performClick()
-            button.performClick()
-            button.performClick()
-        }.then { activity ->
-            assertNotNull(activity.findViewById(46))
-        }
-    }
-
-    @Test
-    fun testKeyTag(): Unit = ensureSetup {
-        compose(
-            """
-            val list = mutableListOf(0,1,2,3)
-
-            @Composable
-            fun Reordering() {
-                LinearLayout {
-                    Recompose { recompose ->
-                        Button(
-                          id=50,
-                          text="Recompose!",
-                          onClick={ list.add(list.removeAt(0)); recompose(); }
-                        )
-                        LinearLayout(id=100) {
-                            for(id in list) {
-                                key(id) {
-                                    StatefulButton()
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            @Composable
-            // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
-            fun StatefulButton() {
-                val count = state { 0 }
-                Button(text="Clicked ${'$'}{count.value} times!", onClick={ count.value++ })
-            }
-            """, noParameters,
-            """
-               Reordering()
-            """
-        ).then { activity ->
-            val layout = activity.findViewById(100) as LinearLayout
-            layout.getChildAt(0).performClick()
-        }.then { activity ->
-            val recomposeButton = activity.findViewById(50) as Button
-            recomposeButton.performClick()
-        }.then { activity ->
-            val layout = activity.findViewById(100) as LinearLayout
-            assertEquals("Clicked 0 times!", (layout.getChildAt(0) as Button).text)
-            assertEquals("Clicked 0 times!", (layout.getChildAt(1) as Button).text)
-            assertEquals("Clicked 0 times!", (layout.getChildAt(2) as Button).text)
-            assertEquals("Clicked 1 times!", (layout.getChildAt(3) as Button).text)
-        }
-    }
-
-    @Test
-    fun testNonFcs(): Unit = ensureSetup {
-        compose(
-            """
-
-            class MyTextView(context: Context) : TextView(context) {}
-
-            fun foo(context: Context): TextView = MyTextView(context=context)
-
-            """, noParameters,
-            """
-            """
-        )
-    }
-
-    @Test
-    fun testNonComposeParameters(): Unit = ensureSetup {
-        compose(
-            """
-                class Action(
-                   val s: String = "",
-                   val param: Int,
-                   type: Set<Int> = setOf(),
-                   val action: () -> Unit
-                )
-
-                @Composable
-                fun DefineAction(
-                    onAction: Action = Action(param = 1) {},
-                    children: @Composable ()->Unit
-                 ) { }
-            """
-        )
-    }
-
-    @Test
-    fun testStableParameters_Various(): Unit = ensureSetup {
-        val output = ArrayList<String>()
-        compose("""
-            val m = mutableStateOf(0)
-
-            @Immutable
-            data class ValueHolder(val value: Int)
-
-            var output = ArrayList<String>()
-
-            class NotStable { val value = 10 }
-
-            @Stable
-            class StableClass {
-                override fun equals(other: Any?) = true
-            }
-
-            enum class EnumState {
-              One,
-              Two
-            }
-
-            val mutableStateType = mutableStateOf(1)
-            val stateType: State<Int> = mutableStateType
-
-            @Composable
-            fun MemoInt(a: Int) {
-              output.add("MemoInt a=${'$'}a")
-              Button(id=101, text="memo ${'$'}a", onClick={ m.value++ })
-            }
-
-            @Composable
-            fun MemoFloat(a: Float) {
-              output.add("MemoFloat")
-              Button(text="memo ${'$'}a")
-            }
-
-            @Composable
-            fun MemoDouble(a: Double) {
-              output.add("MemoDouble")
-              Button(text="memo ${'$'}a")
-            }
-
-            @Composable
-            fun MemoNotStable(a: NotStable) {
-              output.add("MemoNotStable")
-              Button(text="memo ${'$'}{a.value}")
-            }
-
-            @Composable
-            fun MemoModel(a: ValueHolder) {
-              output.add("MemoModelHolder")
-              Button(text="memo ${'$'}{a.value}")
-            }
-
-            @Composable
-            fun MemoEnum(a: EnumState) {
-              output.add("MemoEnum")
-              Button(text="memo ${'$'}{a}")
-            }
-
-            @Composable
-            fun MemoStable(a: StableClass) {
-              output.add("MemoStable")
-              Button(text="memo stable")
-            }
-
-            @Composable
-            fun MemoMutableState(a: MutableState<Int>) {
-              output.add("MemoMutableState")
-              Button(text="memo ${'$'}{a.value}")
-            }
-
-            @Composable
-            fun MemoState(a: State<Int>) {
-              output.add("MemoState")
-              Button(text="memo ${'$'}{a.value}")
-            }
-
-            @Composable
-            fun TestSkipping(
-                a: Int,
-                b: Float,
-                c: Double,
-                d: NotStable,
-                e: ValueHolder,
-                f: EnumState,
-                g: StableClass,
-                h: MutableState<Int>,
-                i: State<Int>
-            ) {
-              val am = a + m.value
-              output.add("TestSkipping a=${'$'}a am=${'$'}am")
-              MemoInt(a=am)
-              MemoFloat(a=b)
-              MemoDouble(a=c)
-              MemoNotStable(a=d)
-              MemoModel(a=e)
-              MemoEnum(a=f)
-              MemoStable(a=g)
-              MemoMutableState(h)
-              MemoState(i)
-            }
-
-            @Composable
-            fun Main(v: ValueHolder, n: NotStable) {
-              TestSkipping(
-                a=1,
-                b=1f,
-                c=2.0,
-                d=NotStable(),
-                e=v,
-                f=EnumState.One,
-                g=StableClass(),
-                h=mutableStateType,
-                i=stateType
-              )
-            }
-        """, {
-            mapOf(
-                "outerOutput: ArrayList<String>" to output
-            )
-        }, """
-            output = outerOutput
-            val v = ValueHolder(0)
-            Main(v, NotStable())
-        """).then {
-            // Expect that all the methods are called in order
-            assertEquals(
-                "TestSkipping a=1 am=1, MemoInt a=1, MemoFloat, " +
-                        "MemoDouble, MemoNotStable, MemoModelHolder, MemoEnum, MemoStable, " +
-                        "MemoMutableState, MemoState",
-                output.joinToString()
-            )
-            output.clear()
-        }.then { activity ->
-            // Expect TestSkipping and MemoNotStable to be called because the test forces an extra compose.
-            assertEquals("TestSkipping a=1 am=1, MemoNotStable", output.joinToString())
-            output.clear()
-
-            // Change the model
-            val button = activity.findViewById(101) as Button
-            button.performClick()
-        }.then {
-            // Expect that only MemoInt (the parameter changed) and MemoNotStable (it has unstable parameters) were
-            // called then expect a second compose which should only MemoNotStable
-            assertEquals(
-                "TestSkipping a=1 am=2, MemoInt a=2, MemoNotStable, " +
-                        "TestSkipping a=1 am=2, MemoNotStable",
-                output.joinToString()
-            )
-        }
-    }
-
-    @Test
-    fun testStableParameters_Lambdas(): Unit = ensureSetup {
-        val output = ArrayList<String>()
-        compose("""
-            val m = mutableStateOf(0)
-
-            var output = ArrayList<String>()
-            val unchanged: () -> Unit = { }
-
-            fun log(msg: String) { output.add(msg) }
-
-            @Composable
-            fun Container(children: @Composable () -> Unit) {
-              log("Container")
-              children()
-            }
-
-            @Composable
-            fun NormalLambda(index: Int, lambda: () -> Unit) {
-              log("NormalLambda(${'$'}index)")
-              Button(text="text")
-            }
-
-            @Composable
-            fun TestSkipping(unchanged: () -> Unit, changed: () -> Unit) {
-              log("TestSkipping")
-              Container {
-                NormalLambda(index = 1, lambda = unchanged)
-                NormalLambda(index = 2, lambda = unchanged)
-                NormalLambda(index = 3, lambda = unchanged)
-                NormalLambda(index = 4, lambda = changed)
-              }
-            }
-
-            fun forceNewLambda(): () -> Unit = { }
-
-            @Composable
-            fun Main(unchanged: () -> Unit) {
-              Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
-              TestSkipping(unchanged = unchanged, changed = forceNewLambda())
-            }
-        """, {
-            mapOf(
-                "outerOutput: ArrayList<String>" to output
-            )
-        }, """
-            output = outerOutput
-            Main(unchanged = unchanged)
-        """).then {
-            // Expect that all the methods are called in order
-            assertEquals(
-                "TestSkipping, Container, NormalLambda(1), " +
-                        "NormalLambda(2), NormalLambda(3), NormalLambda(4)",
-                output.joinToString()
-            )
-            output.clear()
-        }.then { activity ->
-            // Expect nothing to occur with no changes
-            assertEquals("", output.joinToString())
-            output.clear()
-
-            // Change the model
-            val button = activity.findViewById(101) as Button
-            button.performClick()
-        }.then {
-            // Expect only NormalLambda(4) to be called
-            assertEquals(
-                "TestSkipping, NormalLambda(4)",
-                output.joinToString()
-            )
-        }
-    }
-
-    @Test
-    fun testRecomposeScope(): Unit = ensureSetup {
-        compose("""
-            val m = mutableStateOf(0)
-
-            @Composable
-            inline fun InlineContainer(children: @Composable () -> Unit) {
-                children()
-            }
-
-            @Composable
-            fun Container(children: @Composable () -> Unit) {
-                children()
-            }
-
-            @Composable
-            fun Leaf(v: Int) {}
-
-            @Composable
-            fun Inline() {
-                InlineContainer {
-                    Leaf(v = 1)
-                }
-            }
-
-            @Composable
-            fun Lambda() {
-                val a = 1
-                val b = 2
-                Container {
-                    TextView(text = "value = ${'$'}{m.value}", id = 100)
-                    Leaf(v = 1)
-                    Leaf(v = a)
-                    Leaf(v = b)
-                }
-            }
-            """,
-            noParameters,
-            """
-                Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
-                Lambda()
-            """
-        ).then { activity ->
-            assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
-            val button = activity.findViewById<Button>(101)
-            button.performClick()
-        }.then { activity ->
-            assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
-        }
-    }
-
-    @Test
-    fun testRecomposeScope_ReceiverScope(): Unit = ensureSetup {
-        compose("""
-            val m = mutableStateOf(0)
-
-            class Receiver { var r: Int = 0 }
-
-            @Composable
-            fun Container(children: @Composable Receiver.() -> Unit) {
-                Receiver().children()
-            }
-
-            @Composable
-            fun Lambda() {
-                Container {
-                    TextView(text = "value = ${'$'}{m.value}", id = 100)
-                }
-            }
-            """,
-            noParameters,
-            """
-                Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
-                Lambda()
-            """
-        ).then { activity ->
-            assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
-            val button = activity.findViewById<Button>(101)
-            button.performClick()
-        }.then { activity ->
-            assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
-        }
-    }
-
-    @Test
-    fun testRecomposeScope_Method(): Unit = ensureSetup {
-        compose("""
-            val m = mutableStateOf(0)
-
-            @Composable
-            fun Leaf() { }
-
-            class SelfCompose {
-                var f1 = 0
-
-                @Composable
-                fun compose(f2: Int) {
-                    TextView(
-                      text = "f1=${'$'}f1, f2=${'$'}f2, m=${'$'}{m.value*f1*f2}",
-                      id = 100
-                    )
-                }
-            }
-
-            @Composable
-            fun InvokeSelfCompose() {
-                val r = remember() { SelfCompose() }
-                r.f1 = 1
-                r.compose(f2 = 10)
-                Leaf()
-            }
-            """,
-            noParameters,
-            """
-                Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
-                InvokeSelfCompose()
-            """
-        ).then { activity ->
-            assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=0")
-            val button = activity.findViewById<Button>(101)
-            button.performClick()
-        }.then { activity ->
-            assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=10")
-        }
-    }
-
-    fun codegen(text: String, dumpClasses: Boolean = false) {
-        val className = "Test_${uniqueNumber++}"
-        val fileName = "$className.kt"
-
-        classLoader(
-            """
-           import android.content.Context
-           import android.widget.*
-           import androidx.compose.*
-
-           $text
-
-        """, fileName, dumpClasses
-        )
-    }
-
-    fun compose(text: String, dumpClasses: Boolean = false): RobolectricComposeTester = compose(
-        { mapOf<String, Any>() },
-        text,
-        dumpClasses
-    )
-
-    fun <T : Any> compose(
-        valuesFactory: () -> Map<String, T>,
-        text: String,
-        dumpClasses: Boolean = false
-    ) = compose("", valuesFactory, text, dumpClasses)
-
-    private fun execute(block: () -> Unit) {
-        val scheduler = RuntimeEnvironment.getMasterScheduler()
-        scheduler.pause()
-        block()
-        scheduler.advanceToLastPostedRunnable()
-    }
-
-    fun <T : Any> compose(
-        prefix: String,
-        valuesFactory: () -> Map<String, T>,
-        text: String,
-        dumpClasses: Boolean = false
-    ): RobolectricComposeTester {
-        val className = "Test_${uniqueNumber++}"
-        val fileName = "$className.kt"
-
-        val candidateValues = valuesFactory()
-
-        @Suppress("NO_REFLECTION_IN_CLASS_PATH")
-        val parameterList = candidateValues.map {
-            if (it.key.contains(':')) {
-                it.key
-            } else "${it.key}: ${it.value::class.qualifiedName}"
-        }.joinToString()
-        val parameterTypes = candidateValues.map {
-            it.value::class.javaPrimitiveType ?: it.value::class.javaObjectType
-        }.toTypedArray()
-
-        val compiledClasses = classLoader(
-            """
-           import android.content.Context
-           import android.widget.*
-           import android.view.View
-           import androidx.compose.*
-           import androidx.ui.androidview.adapters.*
-
-           $prefix
-
-           class $className {
-
-             @Composable
-             fun test($parameterList) {
-               $text
-             }
-           }
-        """, fileName, dumpClasses
-        )
-
-        val allClassFiles = compiledClasses.allGeneratedFiles.filter {
-            it.relativePath.endsWith(".class")
-        }
-
-        val loader = URLClassLoader(emptyArray(), this.javaClass.classLoader)
-
-        val instanceClass = run {
-            var instanceClass: Class<*>? = null
-            var loadedOne = false
-            for (outFile in allClassFiles) {
-                val bytes = outFile.asByteArray()
-                val loadedClass = loadClass(loader, null, bytes)
-                if (loadedClass.name == className) instanceClass = loadedClass
-                loadedOne = true
-            }
-            if (!loadedOne) error("No classes loaded")
-            instanceClass ?: error("Could not find class $className in loaded classes")
-        }
-
-        val instanceOfClass = instanceClass.newInstance()
-        val testMethod = instanceClass.getMethod(
-            "test",
-            *parameterTypes,
-            Composer::class.java,
-            Int::class.java,
-            Int::class.java
-        )
-
-        return compose { composer, _, _ ->
-            val values = valuesFactory()
-            val arguments = values.map { it.value as Any }.toTypedArray()
-            testMethod.invoke(instanceOfClass, *arguments, composer, 0, 1)
-        }
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    fun View.getComposedSet(tagId: Int): Set<String>? = getTag(tagId) as? Set<String>
-}
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt
index adbfcef..6d32c5c 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt
@@ -79,7 +79,8 @@
     fun testResolutionInsideWhenExpression() = doTest(
         """
             import androidx.compose.*
-            import android.widget.TextView
+            
+            @Composable fun TextView(text: String) { print(text) }
 
             @Composable fun doSomething(foo: Boolean) {
                 when (foo) {
@@ -107,7 +108,7 @@
                 children2: @Composable () -> Unit,
                 value2: Int
             ) {
-                LinearLayout {
+                Foo(123) {
                     // named argument
                     Foo(x=value)
 
@@ -498,13 +499,6 @@
                 <!CANNOT_INFER_PARAMETER_TYPE!>y<!>, <!CANNOT_INFER_PARAMETER_TYPE!>z<!> ->
                     println(x + y + z)
                 }
-
-                Button()
-                LinearLayout()
-
-                LinearLayout {}
-
-                Button <!TOO_MANY_ARGUMENTS!>{}<!>
             }
 
         """.trimIndent()
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 09f4e29..fc9f202 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
@@ -84,7 +84,7 @@
                 if (%default and 0b0010 !== 0) {
                   y = 0
                 }
-                Wrap(restartableFunction(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+                Wrap(composableLambda(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
                   if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                     if (x > 0) {
                       %composer.startReplaceableGroup(<>)
@@ -118,13 +118,9 @@
             }
         """,
         """
-            import androidx.compose.Untracked
-            import androidx.compose.ExperimentalComposeApi
-
             @Composable
             fun Test(x: Int = 0, y: Int = 0) {
-                @OptIn(ExperimentalComposeApi::class)
-                Wrap @Untracked {
+                Wrap @ComposableContract(tracked = false) {
                     A(x)
                 }
             }
@@ -153,7 +149,7 @@
                 if (%default and 0b0010 !== 0) {
                   y = 0
                 }
-                Wrap(restartableFunction(%composer, <>, false) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+                Wrap(composableLambda(%composer, <>, false) { %composer: Composer<*>?, %key: Int, %changed: Int ->
                   %composer.startReplaceableGroup(%key)
                   A(x, 0, %composer, <>, 0b0110 and %dirty, 0b0010)
                   %composer.endReplaceableGroup()
@@ -264,8 +260,8 @@
               } else if (%changed and 0b01100000 === 0) {
                 %dirty = %dirty or if (%composer.changed(arrangement)) 0b01000000 else 0b00100000
               }
-              if (%default and 0b1000 === 0 && %changed and 0b000110000000 === 0) {
-                %dirty = %dirty or if (%composer.changed(crossAxisAlignment)) 0b000100000000 else 0b10000000
+              if (%changed and 0b000110000000 === 0) {
+                %dirty = %dirty or if (%default and 0b1000 === 0 && %composer.changed(crossAxisAlignment)) 0b000100000000 else 0b10000000
               }
               if (%default and 0b00010000 !== 0) {
                 %dirty = %dirty or 0b011000000000
@@ -288,6 +284,7 @@
                   }
                   if (%default and 0b1000 !== 0) {
                     crossAxisAlignment = Companion.Start
+                    %dirty = %dirty and 0b000110000000.inv()
                   }
                   if (%default and 0b00010000 !== 0) {
                     crossAxisSize = SizeMode.Wrap
@@ -295,6 +292,9 @@
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b1000 !== 0) {
+                    %dirty = %dirty and 0b000110000000.inv()
+                  }
                 }
                 println()
               } else {
@@ -321,8 +321,8 @@
               } else if (%changed and 0b00011000 === 0) {
                 %dirty = %dirty or if (%composer.changed(verticalArrangement)) 0b00010000 else 0b1000
               }
-              if (%default and 0b0100 === 0 && %changed and 0b01100000 === 0) {
-                %dirty = %dirty or if (%composer.changed(horizontalGravity)) 0b01000000 else 0b00100000
+              if (%changed and 0b01100000 === 0) {
+                %dirty = %dirty or if (%default and 0b0100 === 0 && %composer.changed(horizontalGravity)) 0b01000000 else 0b00100000
               }
               if (%default and 0b1000 !== 0) {
                 %dirty = %dirty or 0b000110000000
@@ -340,10 +340,14 @@
                   }
                   if (%default and 0b0100 !== 0) {
                     horizontalGravity = Companion.Start
+                    %dirty = %dirty and 0b01100000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0100 !== 0) {
+                    %dirty = %dirty and 0b01100000.inv()
+                  }
                 }
                 val tmp0_orientation = LayoutOrientation.Vertical
                 val tmp1_arrangement = verticalArrangement
@@ -421,18 +425,22 @@
               %composer.startRestartGroup(%key)
               val %dirty = %changed
               val a = a
-              if (%default and 0b0001 === 0 && %changed and 0b0110 === 0) {
-                %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
+              if (%changed and 0b0110 === 0) {
+                %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(a)) 0b0100 else 0b0010
               }
               if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
                   %composer.startDefaults()
                   if (%default and 0b0001 !== 0) {
                     a = newInt()
+                    %dirty = %dirty and 0b0110.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0001 !== 0) {
+                    %dirty = %dirty and 0b0110.inv()
+                  }
                 }
                 print(a)
               } else {
@@ -489,10 +497,14 @@
                   }
                   if (%default and 0b0010 !== 0) {
                     shape = RectangleShape
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
                 println()
               } else {
@@ -533,8 +545,8 @@
               } else if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(modifier)) 0b0100 else 0b0010
               }
-              if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
-                %dirty = %dirty or if (%composer.changed(children)) 0b00010000 else 0b1000
+              if (%changed and 0b00011000 === 0) {
+                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(children)) 0b00010000 else 0b1000
               }
               if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -543,17 +555,21 @@
                     modifier = Companion
                   }
                   if (%default and 0b0010 !== 0) {
-                    children = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+                    children = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
                       if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                         Unit
                       } else {
                         %composer.skipToGroupEnd()
                       }
                     }
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
                 println()
               } else {
@@ -582,7 +598,7 @@
             }
         """,
         """
-            val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
               val %dirty = %changed
               if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -614,7 +630,7 @@
             }
         """,
         """
-            val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
               A(x, %composer, <>, 0b0110 and %changed)
               B(y, %composer, <>, 0b0110 and %changed shr 0b0010)
             }
@@ -655,7 +671,7 @@
             fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
               %composer.startRestartGroup(%key)
               if (%changed !== 0 || !%composer.skipping) {
-                SomeThing(restartableFunction(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+                SomeThing(composableLambda(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
                   if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                     val id = object
                   } else {
@@ -843,8 +859,8 @@
               } else if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
               }
-              if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
-                %dirty = %dirty or if (%composer.changed(b)) 0b00010000 else 0b1000
+              if (%changed and 0b00011000 === 0) {
+                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(b)) 0b00010000 else 0b1000
               }
               if (%default and 0b0100 !== 0) {
                 %dirty = %dirty or 0b01100000
@@ -859,6 +875,7 @@
                   }
                   if (%default and 0b0010 !== 0) {
                     b = makeInt(%composer, <>, 0)
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   if (%default and 0b0100 !== 0) {
                     c = 0
@@ -866,6 +883,9 @@
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
               } else {
                 %composer.skipToGroupEnd()
@@ -936,7 +956,7 @@
                 if (%default and 0b0010 !== 0) {
                   y = 0
                 }
-                Wrap(10, restartableFunction(%composer, <>, true) { it: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+                Wrap(10, composableLambda(%composer, <>, true) { it: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
                   val %dirty = %changed
                   if (%changed and 0b0110 === 0) {
                     %dirty = %dirty or if (%composer.changed(it)) 0b0100 else 0b0010
@@ -994,7 +1014,7 @@
             }
         """,
         """
-            val test: Function4<Int, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { x: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val test: Function4<Int, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { x: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
               val %dirty = %changed
               if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -1102,10 +1122,14 @@
                   }
                   if (%default and 0b0010 !== 0) {
                     b = Foo()
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
                 print("Hello World")
               } else {
@@ -1241,18 +1265,22 @@
               } else if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(text)) 0b0100 else 0b0010
               }
-              if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
-                %dirty = %dirty or if (%composer.changed(color.value)) 0b00010000 else 0b1000
+              if (%changed and 0b00011000 === 0) {
+                %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) {
                   %composer.startDefaults()
                   if (%default and 0b0010 !== 0) {
                     color = Companion.Unset
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
               } else {
                 %composer.skipToGroupEnd()
@@ -1323,7 +1351,7 @@
               %composer.startRestartGroup(%key)
               if (%changed !== 0 || !%composer.skipping) {
                 val x = 123
-                D(restartableFunction(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+                D(composableLambda(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
                   if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                     Unit
                   } else {
@@ -1426,18 +1454,22 @@
               %composer.startRestartGroup(%key)
               val %dirty = %changed
               val x = x
-              if (%default and 0b0001 === 0 && %changed and 0b0110 === 0) {
-                %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
+              if (%changed and 0b0110 === 0) {
+                %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
               }
               if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
                   %composer.startDefaults()
                   if (%default and 0b0001 !== 0) {
                     x = I(%composer, <>, 0)
+                    %dirty = %dirty and 0b0110.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0001 !== 0) {
+                    %dirty = %dirty and 0b0110.inv()
+                  }
                 }
                 A(x, %composer, <>, 0b0110 and %dirty)
               } else {
@@ -1500,10 +1532,14 @@
                   %composer.startDefaults()
                   if (%default and 0b0001 !== 0) {
                     x = Foo()
+                    %dirty = %dirty and 0b0110.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0001 !== 0) {
+                    %dirty = %dirty and 0b0110.inv()
+                  }
                 }
                 A(x, %composer, <>, 0b0110 and %dirty)
               } else {
@@ -1565,13 +1601,21 @@
                   }
                   if (%default and 0b1000 !== 0) {
                     d = Foo()
+                    %dirty = %dirty and 0b000110000000.inv()
                   }
                   if (%default and 0b00010000 !== 0) {
                     e = emptyList()
+                    %dirty = %dirty and 0b011000000000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b1000 !== 0) {
+                    %dirty = %dirty and 0b000110000000.inv()
+                  }
+                  if (%default and 0b00010000 !== 0) {
+                    %dirty = %dirty and 0b011000000000.inv()
+                  }
                 }
                 A(a, b, c, d, e, %composer, <>, 0b0110 and %dirty or 0b00011000 and %dirty or 0b01100000 and %dirty or 0b000110000000 and %dirty or 0b011000000000 and %dirty)
               } else {
@@ -1679,7 +1723,7 @@
             }
         """,
         """
-            val unstableUnused: Function4<Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val unstableUnused: Function4<Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
               val %dirty = %changed
               %dirty = %dirty or 0b0110
               if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
@@ -1688,11 +1732,11 @@
                 %composer.skipToGroupEnd()
               }
             }
-            val unstableUsed: Function4<Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val unstableUsed: Function4<Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
               val %dirty = %changed
               print(x)
             }
-            val stableUnused: Function4<StableFoo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val stableUnused: Function4<StableFoo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
               val %dirty = %changed
               %dirty = %dirty or 0b0110
               if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
@@ -1701,7 +1745,7 @@
                 %composer.skipToGroupEnd()
               }
             }
-            val stableUsed: Function4<StableFoo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+            val stableUsed: Function4<StableFoo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
               val %dirty = %changed
               if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(<this>)) 0b0100 else 0b0010
@@ -1742,13 +1786,13 @@
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
               }
               if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
-                Provide(restartableFunction(%composer, <>, true) { y: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+                Provide(composableLambda(%composer, <>, true) { y: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
                   val %dirty = %changed
                   if (%changed and 0b0110 === 0) {
                     %dirty = %dirty or if (%composer.changed(y)) 0b0100 else 0b0010
                   }
                   if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
-                    Provide(restartableFunction(%composer, <>, true) { z: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+                    Provide(composableLambda(%composer, <>, true) { z: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
                       val %dirty = %changed
                       if (%changed and 0b0110 === 0) {
                         %dirty = %dirty or if (%composer.changed(z)) 0b0100 else 0b0010
@@ -2341,8 +2385,8 @@
               } else if (%changed and 0b0110 === 0) {
                 %dirty = %dirty or if (%composer.changed(wontChange)) 0b0100 else 0b0010
               }
-              if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
-                %dirty = %dirty or if (%composer.changed(mightChange)) 0b00010000 else 0b1000
+              if (%changed and 0b00011000 === 0) {
+                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(mightChange)) 0b00010000 else 0b1000
               }
               if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -2352,10 +2396,14 @@
                   }
                   if (%default and 0b0010 !== 0) {
                     mightChange = AmbientColor.current
+                    %dirty = %dirty and 0b00011000.inv()
                   }
                   %composer.endDefaults()
                 } else {
                   %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
                 }
                 A(wontChange, %composer, <>, 0b0110 and %dirty)
                 A(mightChange, %composer, <>, 0b0110 and %dirty shr 0b0010)
@@ -2397,4 +2445,73 @@
             }
         """
     )
+
+    @Test
+    fun testDefaultsIssue(): Unit = comparisonPropagation(
+        """
+        """,
+        """
+            import androidx.ui.core.Modifier
+            import androidx.ui.unit.Dp
+            import androidx.compose.emptyContent
+
+            @Composable
+            fun Box2(
+                modifier: Modifier = Modifier,
+                paddingStart: Dp = Dp.Unspecified,
+                children: @Composable () -> Unit = emptyContent()
+            ) {
+
+            }
+        """,
+        """
+            @Composable
+            fun Box2(modifier: Modifier?, paddingStart: Dp, children: Function3<Composer<*>, Int, Int, Unit>?, %composer: Composer<*>?, %key: Int, %changed: Int, %default: Int) {
+              %composer.startRestartGroup(%key)
+              val %dirty = %changed
+              val modifier = modifier
+              val paddingStart = paddingStart
+              val children = children
+              if (%default and 0b0001 !== 0) {
+                %dirty = %dirty or 0b0110
+              } else if (%changed and 0b0110 === 0) {
+                %dirty = %dirty or if (%composer.changed(modifier)) 0b0100 else 0b0010
+              }
+              if (%changed and 0b00011000 === 0) {
+                %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(paddingStart.value)) 0b00010000 else 0b1000
+              }
+              if (%default and 0b0100 !== 0) {
+                %dirty = %dirty or 0b01100000
+              } else if (%changed and 0b01100000 === 0) {
+                %dirty = %dirty or if (%composer.changed(children)) 0b01000000 else 0b00100000
+              }
+              if (%dirty and 0b00101011 xor 0b00101010 !== 0 || !%composer.skipping) {
+                if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
+                  %composer.startDefaults()
+                  if (%default and 0b0001 !== 0) {
+                    modifier = Companion
+                  }
+                  if (%default and 0b0010 !== 0) {
+                    paddingStart = Companion.Unspecified
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
+                  if (%default and 0b0100 !== 0) {
+                    children = emptyContent()
+                  }
+                  %composer.endDefaults()
+                } else {
+                  %composer.skipCurrentGroup()
+                  if (%default and 0b0010 !== 0) {
+                    %dirty = %dirty and 0b00011000.inv()
+                  }
+                }
+              } else {
+                %composer.skipToGroupEnd()
+              }
+              %composer.endRestartGroup()?.updateScope { %composer: Composer<*>?, %key: Int, %force: Int ->
+                Box2(modifier, paddingStart, children, %composer, %key, %changed or 0b0001, %default)
+              }
+            }
+        """
+    )
 }
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt
index bb9c6a0..defb9ca 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt
@@ -161,40 +161,6 @@
     }
 
     @Test
-    fun testCrossinlineEmittable(): Unit = ensureSetup {
-        compile(
-            mapOf(
-                "library module" to mapOf(
-                    "x/A.kt" to """
-                    package x
-
-                    import androidx.compose.Composable
-                    import android.widget.LinearLayout
-
-                    @Composable inline fun row(crossinline children: @Composable () -> Unit) {
-                        LinearLayout {
-                            children()
-                        }
-                    }
-                 """
-                ),
-                "Main" to mapOf(
-                    "b/B.kt" to """
-                    package b
-
-                    import androidx.compose.Composable
-                    import x.row
-
-                    @Composable fun Test() {
-                        row { }
-                    }
-                """
-                )
-            )
-        )
-    }
-
-    @Test
     fun testParentNotInitializedBug(): Unit = ensureSetup {
         compile(
             mapOf(
@@ -743,6 +709,7 @@
 
                    import android.widget.*
                    import androidx.compose.*
+                   import androidx.ui.viewinterop.emitView
                    import my.test.lib.*
 
                    var bar = 0
@@ -766,7 +733,10 @@
                    @Composable
                    fun Foo(bar: Int) {
                      InternalComp {
-                       TextView(text="${'$'}bar", id=$tvId)
+                       emitView(::TextView) { 
+                         it.text="${'$'}bar" 
+                         it.id=$tvId
+                       }
                      }
                    }
                 """
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt
index 640f261..91f9d3e 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt
@@ -16,15 +16,12 @@
 
 package androidx.compose.plugins.kotlin
 
-import org.junit.Ignore
-
 class KtxTransformationTest : AbstractCodegenTest() {
 
-    fun testObserveLowering() = ensureSetup { testCompile(
+    fun testObserveLowering() = ensureSetup { testCompileWithViewStubs(
         """
-            import android.widget.Button
-            import androidx.compose.*
-            import androidx.ui.androidview.adapters.setOnClick
+            import androidx.compose.MutableState
+            import androidx.compose.mutableStateOf
 
             @Composable
             fun SimpleComposable() {
@@ -33,7 +30,11 @@
 
             @Composable
             fun FancyButton(state: MutableState<Int>) {
-               Button(text=("Clicked "+state.value+" times"), onClick={state.value++}, id=42)
+               Button(
+                 text=("Clicked "+state.value+" times"),
+                 onClick={state.value++},
+                 id=42
+               )
             }
         """
     ) }
@@ -49,11 +50,8 @@
         """
     ) }
 
-    fun testSingleViewCompose() = ensureSetup { testCompile(
+    fun testSingleViewCompose() = ensureSetup { testCompileWithViewStubs(
         """
-        import androidx.compose.*
-        import android.widget.*
-
         class Foo {
             @Composable
             operator fun invoke() {
@@ -63,11 +61,8 @@
         """
     ) }
 
-    fun testMultipleRootViewCompose() = ensureSetup { testCompile(
+    fun testMultipleRootViewCompose() = ensureSetup { testCompileWithViewStubs(
         """
-        import androidx.compose.*
-        import android.widget.*
-
         class Foo {
             @Composable
             operator fun invoke() {
@@ -79,11 +74,8 @@
         """
     ) }
 
-    fun testNestedViewCompose() = ensureSetup { testCompile(
+    fun testNestedViewCompose() = ensureSetup { testCompileWithViewStubs(
         """
-        import androidx.compose.*
-        import android.widget.*
-
         class Foo {
             @Composable
             operator fun invoke() {
@@ -133,11 +125,8 @@
         """
     ) }
 
-    fun testViewAndComposites() = ensureSetup { testCompile(
+    fun testViewAndComposites() = ensureSetup { testCompileWithViewStubs(
         """
-        import androidx.compose.*
-        import android.widget.*
-
         @Composable
         fun Bar() {}
 
@@ -231,28 +220,8 @@
         """
     ) }
 
-    fun testExtensionFunctions() = ensureSetup { testCompile(
+    fun testChildrenWithTypedParameters() = ensureSetup { testCompileWithViewStubs(
         """
-
-        import androidx.compose.*
-        import android.widget.*
-
-        fun LinearLayout.setSomeExtension(x: Int) {
-        }
-        class X {
-            @Composable
-            operator fun invoke() {
-                LinearLayout(someExtension=123)
-            }
-        }
-        """
-    ) }
-
-    fun testChildrenWithTypedParameters() = ensureSetup { testCompile(
-        """
-        import android.widget.*
-        import androidx.compose.*
-
         @Composable fun HelperComponent(
             children: @Composable (title: String, rating: Int) -> Unit
         ) {
@@ -273,11 +242,8 @@
         """
     ) }
 
-    fun testChildrenCaptureVariables() = ensureSetup { testCompile(
+    fun testChildrenCaptureVariables() = ensureSetup { testCompileWithViewStubs(
         """
-        import android.widget.*
-        import androidx.compose.*
-
         @Composable fun HelperComponent(children: @Composable () -> Unit) {
         }
 
@@ -352,11 +318,8 @@
         )
     }
 
-    fun testChildrenOfNativeView() = ensureSetup { testCompile(
+    fun testChildrenOfNativeView() = ensureSetup { testCompileWithViewStubs(
         """
-        import android.widget.*
-        import androidx.compose.*
-
         class MainComponent {
             @Composable
             operator fun invoke() {
@@ -369,11 +332,8 @@
         """
     ) }
 
-    fun testIrSpecial() = ensureSetup { testCompile(
+    fun testIrSpecial() = ensureSetup { testCompileWithViewStubs(
         """
-        import android.widget.*
-        import androidx.compose.*
-
         @Composable fun HelperComponent(children: @Composable () -> Unit) {}
 
         class MainComponent {
@@ -467,17 +427,6 @@
         """
     ) }
 
-    fun testPackageQualifiedTags() = ensureSetup { testCompile(
-        """
-        import androidx.compose.*
-
-        @Composable
-        fun run() {
-            android.widget.TextView(text="bar")
-        }
-        """
-    ) }
-
     fun testLocalLambda() = ensureSetup { testCompile(
         """
         import androidx.compose.*
@@ -601,11 +550,8 @@
         """
     ) }
 
-    fun testKtxLambdaInIfElse() = ensureSetup { testCompile(
+    fun testKtxLambdaInIfElse() = ensureSetup { testCompileWithViewStubs(
         """
-        import androidx.compose.*
-        import android.widget.TextView
-
         @Composable
         fun foo(x: Boolean) {
             val lambda = @Composable { TextView(text="Hello World") }
@@ -648,52 +594,6 @@
         )
     }
 
-    fun testKtxEmittable() = ensureSetup { testCompileEmittable(
-        """
-
-        open class MockEmittable: Emittable {
-          override fun emitInsertAt(index: Int, instance: Emittable) {}
-          override fun emitRemoveAt(index: Int, count: Int) {}
-          override fun emitMove(from: Int, to: Int, count: Int) {}
-        }
-
-        class MyEmittable: MockEmittable() {
-          var a: Int = 1
-        }
-
-        class Comp {
-            @Composable
-            fun Example() {
-                MyEmittable(a=2)
-            }
-        }
-        """
-    ) }
-
-    @Ignore("b/150394471")
-    fun xtestKtxCompoundEmittable() = ensureSetup { testCompileEmittable(
-        """
-        open class MockEmittable: Emittable {
-          override fun emitInsertAt(index: Int, instance: Emittable) {}
-          override fun emitRemoveAt(index: Int, count: Int) {}
-          override fun emitMove(from: Int, to: Int, count: Int) {}
-        }
-
-        class MyEmittable: MockEmittable() {
-          var a: Int = 1
-        }
-
-        @Composable fun Test() {
-            MyEmittable(a=1) {
-                MyEmittable(a=2)
-                MyEmittable(a=3)
-                MyEmittable(a=4)
-                MyEmittable(a=5)
-            }
-        }
-        """
-    ) }
-
     fun testInvocableObject() = ensureSetup { testCompile(
         """
         import androidx.compose.*
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt
index 749ca47..a17847f 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt
@@ -664,8 +664,7 @@
         @Composable
         fun Example(model: String) {
           workToBeRepeated()
-          @OptIn(androidx.compose.ExperimentalComposeApi::class)
-          Wrapper @Untracked {
+          Wrapper @ComposableContract(tracked = false) {
             workToBeAvoided()
             ValidateModel(model)
           }
@@ -736,7 +735,11 @@
                 @Composable
                 fun TestHost() {
                    println("START: Iteration - ${'$'}iterations")
-                   Button(id=42, onClick=invalidate)
+                   val recompose = invalidate
+                   emitView(::Button) { 
+                     it.id=42 
+                     it.setOnClickListener(View.OnClickListener { recompose() })
+                   }
                    Example("Iteration ${'$'}iterations")
                    println("END  : Iteration - ${'$'}iterations")
                    validate()
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt
index a9aed55..b5a129d 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt
@@ -23,9 +23,11 @@
 import android.widget.LinearLayout
 import androidx.compose.Composer
 import androidx.compose.Composition
+import androidx.compose.ExperimentalComposeApi
 import androidx.compose.Recomposer
 import androidx.compose.compositionFor
-import androidx.ui.node.UiComposer
+import androidx.ui.core.ContextAmbient
+import androidx.ui.node.UiApplier
 import org.robolectric.Robolectric
 import org.robolectric.RuntimeEnvironment
 import org.robolectric.Shadows.shadowOf
@@ -77,12 +79,31 @@
         val root = activity.root
         scheduler.advanceToLastPostedRunnable()
 
-        val composition = compositionFor(root, Recomposer.current()) { slotTable, recomposer ->
-            UiComposer(activity, root, slotTable, recomposer)
+        val startProviders = Composer::class.java.methods.first {
+            it.name.startsWith("startProviders")
+        }
+        val endProviders = Composer::class.java.methods.first {
+            it.name.startsWith("endProviders")
         }
         val setContentMethod = Composition::class.java.methods.first { it.name == "setContent" }
+        startProviders.isAccessible = true
+        endProviders.isAccessible = true
         setContentMethod.isAccessible = true
-        fun setContent() { setContentMethod.invoke(composition, composable) }
+
+        val realComposable: (Composer<*>, Int, Int) -> Unit = { composer, _, _ ->
+            startProviders.invoke(
+                composer,
+                listOf(ContextAmbient provides root.context).toTypedArray()
+            )
+            composable(composer, 0, 0)
+            endProviders.invoke(composer)
+        }
+
+        @OptIn(ExperimentalComposeApi::class)
+        val composition = compositionFor(root, UiApplier(root), Recomposer.current())
+        fun setContent() {
+            setContentMethod.invoke(composition, realComposable)
+        }
         setContent()
         scheduler.advanceToLastPostedRunnable()
         block(activity)
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt
index 5884864..5181116 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt
@@ -60,10 +60,12 @@
     fun testComposableReporting001() {
         checkFail("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             fun myStatelessFunctionalComponent() {
-                TextView(text="Hello World!")
+                Leaf()
             }
 
             fun foo() {
@@ -72,11 +74,13 @@
         """)
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             @Composable
             fun myStatelessFunctionalComponent() {
-                TextView(text="Hello World!")
+                Leaf()
             }
 
             @Composable
@@ -89,17 +93,21 @@
     fun testComposableReporting002() {
         checkFail("""
             import androidx.compose.*;
-            import android.widget.TextView;
 
-            val myLambda1 = { TextView(text="Hello World!") }
-            val myLambda2: () -> Unit = { TextView(text="Hello World!") }
+            @Composable 
+            fun Leaf() {}
+
+            val myLambda1 = { Leaf() }
+            val myLambda2: () -> Unit = { Leaf() }
         """)
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
 
-            val myLambda1 = @Composable { TextView(text="Hello World!") }
-            val myLambda2: @Composable ()->Unit = { TextView(text="Hello World!") }
+            @Composable 
+            fun Leaf() {}
+
+            val myLambda1 = @Composable { Leaf() }
+            val myLambda2: @Composable ()->Unit = { Leaf() }
         """)
     }
 
@@ -114,27 +122,16 @@
         """)
     }
 
-    fun testComposableReporting004() {
-        check("""
-            import androidx.compose.*;
-            import android.widget.TextView;
-
-            @Composable
-            fun foo() {
-                val myRandomLambda = { <!NONE_APPLICABLE!>TextView<!>(text="Hello World!") }
-                System.out.println(myRandomLambda)
-            }
-        """)
-    }
-
     fun testComposableReporting006() {
         checkFail("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             fun foo() {
                 val bar = {
-                    TextView()
+                    Leaf()
                 }
                 bar()
                 System.out.println(bar)
@@ -142,12 +139,14 @@
         """)
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             @Composable
             fun foo() {
                 val bar = @Composable {
-                    TextView()
+                    Leaf()
                 }
                 bar()
                 System.out.println(bar)
@@ -209,35 +208,6 @@
         """)
     }
 
-    fun testComposableReporting016() {
-        check("""
-            import androidx.compose.*;
-
-            <!WRONG_ANNOTATION_TARGET!>@Composable<!>
-            class Noise() {}
-        """)
-
-        check("""
-            import androidx.compose.*;
-
-            val adHoc = <!WRONG_ANNOTATION_TARGET!>@Composable<!> object {
-                var x: Int = 0
-                var y: Int = 0
-            }
-        """)
-
-        check("""
-            import androidx.compose.*;
-
-            open class Noise() {}
-
-            val adHoc = <!WRONG_ANNOTATION_TARGET!>@Composable<!> object : Noise() {
-                var x: Int = 0
-                var y: Int = 0
-            }
-        """)
-    }
-
     fun testComposableReporting017() {
         checkFail("""
             import androidx.compose.*;
@@ -274,20 +244,23 @@
     fun testComposableReporting018() {
         checkFail("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             fun foo() {
-                val myVariable: ()->Unit = @Composable { TextView(text="Hello World!") }
+                val myVariable: ()->Unit = @Composable { Leaf() }
                 System.out.println(myVariable)
             }
         """)
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             fun foo() {
-                val myVariable: ()->Unit = <!TYPE_MISMATCH!>@Composable {
-                 TextView(text="Hello World!") }<!>
+                val myVariable: ()->Unit = <!TYPE_MISMATCH!>@Composable { Leaf() }<!>
                 System.out.println(myVariable)
             }
         """)
@@ -296,13 +269,15 @@
     fun testComposableReporting021() {
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             @Composable
             fun foo() {
                 val myList = listOf(1,2,3,4,5)
                 myList.forEach @Composable { value: Int -> 
-                    TextView(text=value.toString())
+                    Leaf()
                     System.out.println(value)
                 }
             }
@@ -312,12 +287,14 @@
     fun testComposableReporting022() {
         checkFail("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             fun foo() {
                 val myList = listOf(1,2,3,4,5)
                 myList.forEach { value: Int -> 
-                    TextView(text=value.toString()) 
+                    Leaf() 
                     System.out.println(value)
                 }
             }
@@ -326,10 +303,13 @@
             import androidx.compose.*;
             import android.widget.TextView;
 
+            @Composable 
+            fun Leaf() {}
+
             fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>() {
                 val myList = listOf(1,2,3,4,5)
                 myList.forEach @Composable { value: Int -> 
-                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>TextView<!>(text=value.toString())
+                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE, COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Leaf<!>()
                     System.out.println(value) 
                 }
             }
@@ -339,12 +319,14 @@
     fun testComposableReporting024() {
         check("""
             import androidx.compose.*;
+            import android.widget.LinearLayout
             import androidx.ui.core.setViewContent
-            import android.widget.TextView;
-            import android.widget.LinearLayout;
+
+            @Composable 
+            fun Leaf() {}
 
             fun foo(ll: LinearLayout) {
-                ll.setViewContent { TextView(text="Hello World!") }
+                ll.setViewContent { Leaf() }
             }
         """)
     }
@@ -352,11 +334,13 @@
     fun testComposableReporting025() {
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
 
             @Composable
             fun foo() {
-                listOf(1,2,3,4,5).forEach { TextView(text="Hello World!") }
+                listOf(1,2,3,4,5).forEach { Leaf() }
             }
         """)
     }
@@ -364,13 +348,17 @@
     fun testComposableReporting026() {
         check("""
             import androidx.compose.*;
-            import android.widget.LinearLayout;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
+
+            @Composable 
+            fun Group(content: @Composable () -> Unit) { content() }
 
             @Composable
             fun foo() {
-                LinearLayout {
-                    TextView(text="Hello Jim!")
+                Group {
+                    Leaf()
                 }
             }
         """)
@@ -379,14 +367,18 @@
     fun testComposableReporting027() {
         check("""
             import androidx.compose.*;
-            import android.widget.LinearLayout;
-            import android.widget.TextView;
+
+            @Composable 
+            fun Leaf() {}
+
+            @Composable 
+            fun Group(content: @Composable () -> Unit) { content() }
 
             @Composable
             fun foo() {
-                LinearLayout {
+                Group {
                     listOf(1,2,3).forEach {
-                        TextView(text="Hello Jim!")
+                        Leaf()
                     }
                 }
             }
@@ -442,14 +434,16 @@
     fun testComposableReporting032() {
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
 
             @Composable
             fun MyComposable(children: @Composable ()->Unit) { children() }
 
+            @Composable 
+            fun Leaf() {}
+
             @Composable
             fun foo() {
-                MyComposable { TextView(text="Hello") }
+                MyComposable { Leaf() }
             }
         """)
     }
@@ -457,14 +451,16 @@
     fun testComposableReporting033() {
         check("""
             import androidx.compose.*;
-            import android.widget.TextView;
 
             @Composable
             fun MyComposable(children: @Composable ()->Unit) { children() }
 
+            @Composable 
+            fun Leaf() {}
+
             @Composable
             fun foo() {
-                MyComposable(children={ TextView(text="Hello")})
+                MyComposable(children={ Leaf() })
             }
         """)
     }
@@ -576,19 +572,19 @@
         check(
             """
             import androidx.compose.*
-            import android.widget.TextView;
 
             fun composeInto(l: @Composable ()->Unit) { System.out.println(l) }
 
             fun Foo() {
                 composeInto {
-                    TextView(text="Hello World")
+                    Baz()
                 }
             }
 
             fun Bar() {
                 Foo()
             }
+            @Composable fun Baz() {}
         """
         )
     }
@@ -643,7 +639,7 @@
             fun FancyButton() {}
 
             fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Noise<!>() {
-                <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>FancyButton<!>()
+                <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>FancyButton<!>()
             }
         """)
     }
@@ -651,7 +647,6 @@
     fun testComposableReporting044() {
         check("""
             import androidx.compose.*
-            import android.widget.TextView;
 
             typealias UNIT_LAMBDA = () -> Unit
 
@@ -678,23 +673,6 @@
         """)
     }
 
-    fun testComposableReporting047() {
-        check("""
-            import androidx.compose.*
-            import android.widget.LinearLayout;
-
-            @Composable
-            fun FancyButton() {}
-
-            @Composable
-            fun Foo() {
-                LinearLayout {
-                    FancyButton()
-                }
-            }
-        """)
-    }
-
     fun testComposableReporting048() {
         // Type inference for non-null @Composable lambdas
         checkFail("""
@@ -889,7 +867,7 @@
             @Composable fun foo(): Int = 123
 
             fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>App<!>() {
-                val x = <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>()
+                val x = <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>()
                 print(x)
             }
         """)
@@ -902,25 +880,25 @@
             @Composable fun Foo() {}
 
             val y: Any <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>get() = 
-            <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 1 }<!>
+            <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 1 }<!>
 
             fun App() {
                 val x = object {
                   val a <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>get() = 
-                  <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 2 }<!>
+                  <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 2 }<!>
                   @Composable val c get() = state { 4 }
                   @Composable fun bar() { Foo() }
                   fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>() {
-                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>() 
+                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>() 
                   }
                 }
                 class Bar {
                   val b <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>get() =
-                  <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 6 }<!>
+                  <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 6 }<!>
                   @Composable val c get() = state { 7 }
                 }
                 fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Bam<!>() {
-                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
+                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
                 }
                 @Composable fun Boo() {
                     Foo()
@@ -942,7 +920,7 @@
                   <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!><!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!><!> { 2 }<!>
                   @Composable val c get() = state { 4 }
                   fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>() { 
-                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>() 
+                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>() 
                   }
                   @Composable fun bar() { Foo() }
                 }
@@ -952,7 +930,7 @@
                   @Composable val c get() = state { 7 }
                 }
                 fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Bam<!>() {
-                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
+                    <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
                 }
                 @Composable fun Boo() {
                     Foo()
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt
index 90495b6..f5ec4af 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt
@@ -36,7 +36,6 @@
 import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
 import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
 import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
-import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.psi.KtAnnotatedExpression
 import org.jetbrains.kotlin.psi.KtAnnotationEntry
 import org.jetbrains.kotlin.psi.KtCallExpression
@@ -63,8 +62,6 @@
 import org.jetbrains.kotlin.resolve.BindingTrace
 import org.jetbrains.kotlin.platform.TargetPlatform
 import org.jetbrains.kotlin.platform.jvm.isJvm
-import org.jetbrains.kotlin.psi.KtFunctionLiteral
-import org.jetbrains.kotlin.psi.KtLambdaArgument
 import org.jetbrains.kotlin.psi.KtPropertyAccessor
 import org.jetbrains.kotlin.psi.KtSimpleNameExpression
 import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
@@ -83,7 +80,6 @@
 import org.jetbrains.kotlin.types.typeUtil.builtIns
 import org.jetbrains.kotlin.types.upperIfFlexible
 import org.jetbrains.kotlin.util.OperatorNameConventions
-import org.jetbrains.kotlin.utils.addToStdlib.cast
 
 open class ComposableAnnotationChecker : CallChecker, DeclarationChecker,
     AdditionalTypeChecker, AdditionalAnnotationChecker, StorageComponentContainerContributor {
@@ -140,10 +136,6 @@
         }
         val psi = unwrappedDescriptor.findPsi() as? KtElement
         psi?.let { trace.bindingContext.get(COMPOSABLE_ANALYSIS, it)?.let { return it } }
-        if (unwrappedDescriptor.name == Name.identifier("compose") &&
-            unwrappedDescriptor.containingDeclaration is ClassDescriptor &&
-            ComposeUtils.isComposeComponent(unwrappedDescriptor.containingDeclaration)
-        ) return Composability.MARKED
         var composability = Composability.NOT_COMPOSABLE
         if (trace.bindingContext.get(
                 INFERRED_COMPOSABLE_DESCRIPTOR,
@@ -167,9 +159,6 @@
                 is AnonymousFunctionDescriptor -> {
                     if (unwrappedDescriptor.hasComposableAnnotation()) composability =
                         Composability.MARKED
-                    if (psi is KtFunctionLiteral && psi.isEmitInline(trace.bindingContext)) {
-                        composability = Composability.MARKED
-                    }
                 }
                 is PropertyGetterDescriptor ->
                     if (unwrappedDescriptor.correspondingProperty.hasComposableAnnotation())
@@ -251,7 +240,6 @@
                 reportElement: KtExpression
             ) {
                 when (resolvedCall?.candidateDescriptor) {
-                    is ComposableEmitDescriptor,
                     is ComposablePropertyDescriptor,
                     is ComposableFunctionDescriptor -> {
                         localFcs = true
@@ -314,13 +302,11 @@
             Composability.NOT_COMPOSABLE
 
         if (element is KtClass) {
-            val descriptor = trace.bindingContext.get(BindingContext.CLASS, element)
-                ?: error("Element class context not found")
             val annotationEntry = element.annotationEntries.singleOrNull {
                 trace.bindingContext.get(BindingContext.ANNOTATION, it)?.isComposableAnnotation
                     ?: false
             }
-            if (annotationEntry != null && !ComposeUtils.isComposeComponent(descriptor)) {
+            if (annotationEntry != null) {
                 trace.report(
                     Errors.WRONG_ANNOTATION_TARGET.on(
                         annotationEntry,
@@ -328,9 +314,6 @@
                     )
                 )
             }
-            if (ComposeUtils.isComposeComponent(descriptor)) {
-                composability += Composability.MARKED
-            }
         }
         if (element is KtParameter) {
             val composableAnnotation = element
@@ -380,15 +363,6 @@
         }
 
         if (element is KtLambdaExpression || element is KtFunction) {
-            val associatedCall = parent?.parent as? KtCallExpression
-
-            if (associatedCall != null && parent is KtLambdaArgument) {
-                val resolvedCall = associatedCall.getResolvedCall(trace.bindingContext)
-                if (resolvedCall?.candidateDescriptor is ComposableEmitDescriptor) {
-                    composability += Composability.MARKED
-                }
-            }
-
             composability = analyzeFunctionContents(trace, element, composability)
         }
 
@@ -415,19 +389,13 @@
                 val trace = context.trace
                 val element = descriptor.findPsi()
                 if (element is KtClass) {
-                    val classDescriptor =
-                        trace.bindingContext.get(
-                            BindingContext.CLASS,
-                            element
-                        ) ?: error("Element class context not found")
                     val composableAnnotationEntry = element.annotationEntries.singleOrNull {
                         trace.bindingContext.get(
                             BindingContext.ANNOTATION,
                             it
                         )?.isComposableAnnotation ?: false
                     }
-                    if (composableAnnotationEntry != null &&
-                        !ComposeUtils.isComposeComponent(classDescriptor)) {
+                    if (composableAnnotationEntry != null) {
                         trace.report(
                             Errors.WRONG_ANNOTATION_TARGET.on(
                                 composableAnnotationEntry,
@@ -480,19 +448,6 @@
                     )
                 if (isInlineable) return
 
-                if (expression.parent is KtLambdaArgument) {
-                    val callDescriptor = expression
-                        .parent
-                        ?.parent
-                        ?.cast<KtCallExpression>()
-                        ?.getResolvedCall(c.trace.bindingContext)
-                        ?.candidateDescriptor
-
-                    if (callDescriptor is ComposableEmitDescriptor) {
-                        return
-                    }
-                }
-
                 val reportOn =
                     if (expression.parent is KtAnnotatedExpression)
                         expression.parent as KtExpression
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableEmitDescriptor.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableEmitDescriptor.kt
deleted file mode 100644
index 920ab4d..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableEmitDescriptor.kt
+++ /dev/null
@@ -1,211 +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.plugins.kotlin
-
-import org.jetbrains.kotlin.builtins.DefaultBuiltIns
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.SourceElement
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.descriptors.Visibilities
-import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
-import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.replace
-import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
-
-interface ComposableEmitMetadata {
-    val composerMetadata: ComposerMetadata
-    val emitCall: ResolvedCall<*>
-    val hasChildren: Boolean
-    val pivotals: List<String>
-    val ctorCall: ResolvedCall<*>
-    val ctorParams: List<String>
-    val validations: List<ValidatedAssignment>
-}
-
-class ComposableEmitDescriptor(
-    override val composerMetadata: ComposerMetadata,
-    override val emitCall: ResolvedCall<*>,
-    override val hasChildren: Boolean,
-    override val pivotals: List<String>,
-    override val ctorCall: ResolvedCall<*>,
-    override val ctorParams: List<String>,
-    override val validations: List<ValidatedAssignment>,
-    containingDeclaration: DeclarationDescriptor,
-    original: SimpleFunctionDescriptor?,
-    annotations: Annotations,
-    name: Name,
-    kind: CallableMemberDescriptor.Kind,
-    source: SourceElement
-) : ComposableEmitMetadata, SimpleFunctionDescriptorImpl(
-    containingDeclaration,
-    original,
-    annotations,
-    name,
-    kind,
-    source
-) {
-
-    companion object {
-        fun build(
-            hasChildren: Boolean,
-            emitCall: ResolvedCall<*>,
-            pivotals: List<String>,
-            ctorCall: ResolvedCall<*>,
-            ctorParams: List<String>,
-            validations: List<ValidatedAssignment>,
-            composerMetadata: ComposerMetadata,
-            name: Name
-        ): ComposableEmitDescriptor {
-
-            val builtIns = DefaultBuiltIns.Instance
-
-            val resolvedCall = ctorCall
-
-            val original = resolvedCall.resultingDescriptor as? SimpleFunctionDescriptor
-
-            val descriptor = ComposableEmitDescriptor(
-                composerMetadata,
-                emitCall,
-                hasChildren,
-                pivotals,
-                ctorCall,
-                ctorParams,
-                validations,
-                emitCall.candidateDescriptor.containingDeclaration,
-                original,
-                Annotations.EMPTY,
-                name,
-                CallableMemberDescriptor.Kind.SYNTHESIZED,
-                SourceElement.NO_SOURCE
-            )
-
-            val valueArgs = mutableListOf<ValueParameterDescriptor>()
-            val paramSet = mutableSetOf<String>()
-
-            for (paramName in ctorParams) {
-                if (paramSet.contains(paramName)) continue
-                val param = resolvedCall.resultingDescriptor.valueParameters.find {
-                    it.name.identifier == paramName
-                } ?: continue
-
-                paramSet.add(paramName)
-                valueArgs.add(
-                    ValueParameterDescriptorImpl(
-                        descriptor, null, valueArgs.size,
-                        Annotations.EMPTY,
-                        param.name,
-                        param.type, false,
-                        false,
-                        false, null,
-                        SourceElement.NO_SOURCE
-                    )
-                )
-            }
-
-            for (validation in validations) {
-                if (paramSet.contains(validation.name)) continue
-                paramSet.add(validation.name)
-                valueArgs.add(
-                    ValueParameterDescriptorImpl(
-                        descriptor,
-                        null,
-                        valueArgs.size,
-                        Annotations.EMPTY,
-                        Name.identifier(validation.name),
-                        validation.type,
-                        false,
-                        false,
-                        false,
-                        null,
-                        SourceElement.NO_SOURCE
-                    )
-                )
-            }
-
-            val unitLambdaType = builtIns.getFunction(
-                0
-            ).defaultType.replace(
-                listOf(builtIns.unitType.asTypeProjection())
-            )
-            // NOTE(lmr): it's actually kind of important that this is *not* a composable lambda,
-            // so that the observe patcher doesn't insert an observe scope.
-            // In the future, we should reconsider how this is done since semantically a composable
-            // lambda is more correct here. I tried, but had trouble passing enough information to
-            // the observe patcher so it knew not to do this.
-            /*.makeComposable(scopeTower.module)*/
-            if (hasChildren) {
-                valueArgs.add(
-                    EmitChildrenValueParameterDescriptor(
-                        descriptor, null, valueArgs.size,
-                        Annotations.EMPTY,
-                        Name.identifier("\$CHILDREN"),
-                        unitLambdaType, false,
-                        false,
-                        false, null,
-                        SourceElement.NO_SOURCE
-                    )
-                )
-            }
-
-            descriptor.initialize(
-                null,
-                null,
-                mutableListOf(),
-                valueArgs,
-                builtIns.unitType,
-                Modality.FINAL,
-                Visibilities.DEFAULT_VISIBILITY
-            )
-
-            return descriptor
-        }
-    }
-}
-
-class EmitChildrenValueParameterDescriptor(
-    containingDeclaration: CallableDescriptor,
-    original: ValueParameterDescriptor?,
-    index: Int,
-    annotations: Annotations,
-    name: Name,
-    outType: KotlinType,
-    declaresDefaultValue: Boolean,
-    isCrossinline: Boolean,
-    isNoinline: Boolean,
-    varargElementType: KotlinType?,
-    source: SourceElement
-) : ValueParameterDescriptorImpl(
-    containingDeclaration,
-    original,
-    index,
-    annotations,
-    name,
-    outType,
-    declaresDefaultValue,
-    isCrossinline,
-    isNoinline,
-    varargElementType,
-    source
-)
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt
index f643a21..843f682 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt
@@ -16,42 +16,29 @@
 
 package androidx.compose.plugins.kotlin
 
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
 import com.intellij.psi.PsiElement
 import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
 import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
 import org.jetbrains.kotlin.extensions.internal.CallResolutionInterceptorExtension
 import org.jetbrains.kotlin.incremental.components.LookupLocation
-import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.psi.KtExpression
 import org.jetbrains.kotlin.psi.KtFunction
-import org.jetbrains.kotlin.psi.KtPsiFactory
 import org.jetbrains.kotlin.resolve.BindingContext
 import org.jetbrains.kotlin.resolve.calls.CallResolver
 import org.jetbrains.kotlin.resolve.calls.CandidateResolver
 import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
 import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
-import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl
 import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
 import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionMutableResolvedCall
 import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
 import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
-import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
 import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
 import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
 import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
 import org.jetbrains.kotlin.resolve.inline.InlineUtil
 import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
-import org.jetbrains.kotlin.types.KotlinType
 
 typealias Candidate = NewResolutionOldInference.MyCandidate
 
@@ -88,18 +75,21 @@
         when (val descriptor = underlying.candidateDescriptor) {
             is FunctionDescriptor -> ComposableFunctionDescriptor(descriptor)
             is PropertyDescriptor -> ComposablePropertyDescriptorImpl(descriptor)
-            else -> error("Expected FunctionDescriptor or PropertyDescriptor, found $descriptor")
+            else -> descriptor
         }
     override fun getCandidateDescriptor(): T = composableCandidateDescriptor as T
     override fun getResultingDescriptor(): T {
         return when (val descriptor = underlying.resultingDescriptor) {
             is FunctionDescriptor -> ComposableFunctionDescriptor(descriptor)
             is PropertyDescriptor -> ComposablePropertyDescriptorImpl(descriptor)
-            else -> error("Expected FunctionDescriptor or PropertyDescriptor, found $descriptor")
+            else -> descriptor
         } as T
     }
 }
 
+// TODO(lmr): This class is only needed for the syntax highlighting for composable calls right
+//  now. The ComposableFunctionDescriptors are not otherwise needed. We should refactor the
+//  syntax highlighting plugin ASAP so that we can get rid of this plugin.
 @Suppress("INVISIBLE_REFERENCE", "EXPERIMENTAL_IS_NOT_ENABLED")
 @OptIn(org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints::class)
 open class ComposeCallResolutionInterceptorExtension : CallResolutionInterceptorExtension {
@@ -112,67 +102,36 @@
         kind: NewResolutionOldInference.ResolutionKind,
         tracing: TracingStrategy
     ): Collection<Candidate> {
-        if (callResolver == null) throw IllegalArgumentException("Call resolver must be non-null")
-
         if (candidates.isEmpty()) return candidates
-        val bindingContext = context.trace.bindingContext
-        val call = context.call
-        val shouldIgnore = bindingContext[
-                ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-                call
-        ] ?: false
 
-        if (shouldIgnore) return candidates
-
+        val others = mutableListOf<Candidate>()
         val composables = mutableListOf<Candidate>()
-        val nonComposablesNonConstructors = mutableListOf<Candidate>()
-        val alreadyInterceptedCandidates = mutableListOf<Candidate>()
-        val constructors = mutableListOf<Candidate>()
-
-        var needToLookupComposer = false
 
         for (candidate in candidates) {
             val resolvedCall = candidate.resolvedCall
             val candidateDescriptor = resolvedCall.candidateDescriptor
             when {
                 candidateDescriptor is ComposableFunctionDescriptor -> {
-                    alreadyInterceptedCandidates.add(candidate)
-                }
-                candidateDescriptor is ComposableEmitDescriptor -> {
-                    alreadyInterceptedCandidates.add(candidate)
+                    others.add(candidate)
                 }
                 resolvedCall is VariableAsFunctionResolvedCall &&
                 resolvedCall.variableCall
                     .candidateDescriptor
                     .type
                     .hasComposableAnnotation() -> {
-                    needToLookupComposer = true
                     composables.add(candidate)
                 }
                 resolvedCall.candidateDescriptor.hasComposableAnnotation() -> {
-                    needToLookupComposer = true
                     composables.add(candidate)
                 }
-                resolvedCall.candidateDescriptor is ConstructorDescriptor -> {
-                    needToLookupComposer = true
-                    constructors.add(candidate)
-                }
-                else -> nonComposablesNonConstructors.add(candidate)
+                else -> others.add(candidate)
             }
         }
 
-        // If none of the candidates are composable or constructors, then it's unnecessary for us
-        // to do any work at all, since it will never be anything we intercept
-        if (!needToLookupComposer) return candidates
-
-        if (!isInComposableScope(context)) return candidates
-
-        // NOTE(lmr): I'm not implementing emittable interception here, since I believe it is not
-        // needed. So in this case we just pass constructors right through, untouched.
-        return nonComposablesNonConstructors +
-                constructors +
-                alreadyInterceptedCandidates +
-                composables.map { ComposableCandidate(it) }
+        return when {
+            composables.isEmpty() || !isInComposableScope(context) -> candidates
+            else -> others + composables.map { ComposableCandidate(it) }
+        }
     }
 
     override fun interceptCandidates(
@@ -184,128 +143,22 @@
         name: Name,
         location: LookupLocation
     ): Collection<FunctionDescriptor> {
-        val element = resolutionContext.call.callElement as KtExpression
-        val project = element.project
-        if (callResolver == null) throw IllegalArgumentException("Call resolver must be non-null")
-
-        if (candidates.isEmpty()) return candidates
-        val bindingContext = resolutionContext.trace.bindingContext
-        val call = resolutionContext.call
-        val shouldIgnore = bindingContext[
-                ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-                call
-        ] ?: false
-
-        if (shouldIgnore) return candidates
-
+        val others = mutableListOf<FunctionDescriptor>()
         val composables = mutableListOf<FunctionDescriptor>()
-        val nonComposablesNonConstructors = mutableListOf<FunctionDescriptor>()
-        val constructors = mutableListOf<ConstructorDescriptor>()
-
-        var needToLookupComposer = false
 
         for (candidate in candidates) {
             when {
                 candidate.hasComposableAnnotation() -> {
-                    needToLookupComposer = true
                     composables.add(candidate)
                 }
-                candidate is ConstructorDescriptor -> {
-                    needToLookupComposer = true
-                    constructors.add(candidate)
-                }
-                else -> nonComposablesNonConstructors.add(candidate)
+                else -> others.add(candidate)
             }
         }
 
-        // If none of the candidates are composable or constructors, then it's unnecessary for us
-        // to do any work at all, since it will never be anything we intercept
-        if (!needToLookupComposer) return candidates
-
-        // If there are no constructors, then all of the candidates are either composables or
-        // non-composable functions, and we follow normal resolution rules.
-        if (constructors.isEmpty()) {
-            // we wrap the composable descriptors into a ComposableFunctionDescriptor so we know
-            // to intercept it in the backend.
-            return nonComposablesNonConstructors + composables.map {
-                ComposableFunctionDescriptor(it)
-            }
+        return when {
+            composables.isEmpty() || !isInComposableScope(resolutionContext) -> candidates
+            else -> others + composables.map { ComposableFunctionDescriptor(it) }
         }
-
-        if (!isInComposableScope(resolutionContext)) return candidates
-
-        val composerType = callResolver.findComposerCallAndDescriptor(resolutionContext)
-            ?: return nonComposablesNonConstructors + constructors
-
-        val psiFactory = KtPsiFactory(project, markGenerated = false)
-
-        // If we made it this far, we need to check and see if the constructors qualify as emit
-        // calls instead of constructor calls.  First, we need to look at the composer to see
-        // what kinds of "emittables" it accepts.
-        // We cache the metadata into a writeable slice based on the descriptor
-        val composerMetadata = ComposerMetadata.getOrBuild(
-            composerType,
-            callResolver,
-            psiFactory,
-            resolutionContext
-        )
-
-        val emittables = constructors.filter {
-            composerMetadata.isEmittable(it.returnType) && !it.returnType.isAbstract()
-        }
-        val hasEmittableCandidate = emittables.isNotEmpty()
-
-        // if none of the constructors are emittables, then all of the candidates are valid
-        if (!hasEmittableCandidate) {
-            return nonComposablesNonConstructors + constructors + composables.map {
-                ComposableFunctionDescriptor(it)
-            }
-        }
-
-        // since some of the constructors are emittables, we fall back to resolving using the
-        // emit resolver.
-        val emitResolver = ComposeEmitResolver(
-            callResolver,
-            project,
-            composerMetadata
-        )
-
-        val emitCandidates = emitResolver.resolveCandidates(
-            call,
-            emittables,
-            name,
-            resolutionContext
-        )
-
-        return nonComposablesNonConstructors +
-                composables.map {
-                    ComposableFunctionDescriptor(it)
-                } +
-                constructors.filter { !composerMetadata.isEmittable(it.returnType) } +
-                emitCandidates
-    }
-
-    private fun CallResolver.findComposerCallAndDescriptor(
-        context: BasicCallResolutionContext
-    ): KotlinType? {
-        // use the call resolver to find any variable that would resolve with "composer" in scope.
-        return resolveComposer(context)?.resultingDescriptor?.returnType
-            // If there is no composer in scope, then we decide to fall back to the ViewComposer
-            // as a default. When we are properly inferring the composer type, this step should no
-            // longer be needed. This provides a better developer experience currently though since
-            // developers won't be required to import the composer into scope.
-            ?: context
-                .scope
-                .ownerDescriptor
-                .module
-                .findClassAcrossModuleDependencies(ClassId.topLevel(ComposeFqNames.UiComposer))
-                ?.defaultType
-            ?: context
-                .scope
-                .ownerDescriptor
-                .module
-                .findClassAcrossModuleDependencies(ClassId.topLevel(ComposeFqNames.Composer))
-                ?.defaultType
     }
 
     private fun isInComposableScope(resolutionContext: BasicCallResolutionContext): Boolean {
@@ -352,52 +205,4 @@
         }
         return false
     }
-
-    private fun CallResolver.resolveVar(
-        name: Name,
-        context: BasicCallResolutionContext
-    ): OverloadResolutionResults<CallableDescriptor> {
-        val temporaryForVariable = TemporaryTraceAndCache.create(
-            context,
-            "trace to resolve variable",
-            context.call.callElement as KtExpression
-        )
-        val call = makeCall(context.call.callElement)
-        val contextForVariable = BasicCallResolutionContext.create(
-            context.replaceTraceAndCache(temporaryForVariable),
-            call,
-            CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-            DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call)
-
-        )
-        contextForVariable.trace.record(
-            ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-            call,
-            true
-        )
-        return computeTasksAndResolveCall<CallableDescriptor>(
-            contextForVariable,
-            name,
-            TracingStrategy.EMPTY,
-            NewResolutionOldInference.ResolutionKind.Variable
-        )
-    }
-
-    private fun CallResolver.resolveComposer(context: BasicCallResolutionContext):
-            ResolvedCall<CallableDescriptor>? {
-
-        // The composer is currently resolved as whatever is currently in scope with the name "composer".
-        val resolvedComposer = resolveVar(KtxNameConventions.COMPOSER, context)
-
-        if (!resolvedComposer.isSuccess) {
-            return null
-        }
-
-        return resolvedComposer.resultingCall
-    }
-
-    private fun KotlinType.isAbstract(): Boolean {
-        val modality = (constructor.declarationDescriptor as? ClassDescriptor)?.modality
-        return modality == Modality.ABSTRACT || modality == Modality.SEALED
-    }
 }
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeEmitResolver.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeEmitResolver.kt
deleted file mode 100644
index e5b8bf0..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeEmitResolver.kt
+++ /dev/null
@@ -1,1580 +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.plugins.kotlin
-
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import com.intellij.lang.ASTNode
-import com.intellij.openapi.project.Project
-import com.intellij.psi.impl.source.tree.LeafPsiElement
-import com.intellij.util.SmartList
-import org.jetbrains.kotlin.builtins.DefaultBuiltIns
-import org.jetbrains.kotlin.builtins.createFunctionType
-import org.jetbrains.kotlin.builtins.extractParameterNameFromFunctionTypeArgument
-import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
-import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
-import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
-import org.jetbrains.kotlin.builtins.isExtensionFunctionType
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.ClassKind
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
-import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
-import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.descriptors.VariableDescriptor
-import org.jetbrains.kotlin.descriptors.Visibilities
-import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.diagnostics.Severity
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi.Call
-import org.jetbrains.kotlin.psi.KtElement
-import org.jetbrains.kotlin.psi.KtExpression
-import org.jetbrains.kotlin.psi.KtLambdaArgument
-import org.jetbrains.kotlin.psi.KtPsiFactory
-import org.jetbrains.kotlin.psi.KtQualifiedExpression
-import org.jetbrains.kotlin.psi.KtReferenceExpression
-import org.jetbrains.kotlin.psi.KtSimpleNameExpression
-import org.jetbrains.kotlin.psi.ValueArgument
-import org.jetbrains.kotlin.psi.ValueArgumentName
-import org.jetbrains.kotlin.builtins.isFunctionType
-import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
-import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.descriptors.SourceElement
-import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
-import org.jetbrains.kotlin.psi.KtTypeArgumentList
-import org.jetbrains.kotlin.psi.KtTypeProjection
-import org.jetbrains.kotlin.psi.KtValueArgumentList
-import org.jetbrains.kotlin.psi.LambdaArgument
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.BindingTrace
-import org.jetbrains.kotlin.resolve.DescriptorFactory
-import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
-import org.jetbrains.kotlin.resolve.calls.CallResolver
-import org.jetbrains.kotlin.resolve.calls.checkers.UnderscoreUsageChecker
-import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
-import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
-import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
-import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
-import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus
-import org.jetbrains.kotlin.resolve.calls.model.ArgumentUnmapped
-import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl
-import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
-import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
-import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
-import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
-import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
-import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
-import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
-import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
-import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl
-import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference
-import org.jetbrains.kotlin.resolve.calls.util.CallMaker
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
-import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
-import org.jetbrains.kotlin.resolve.scopes.MemberScope
-import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
-import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
-import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
-import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
-import org.jetbrains.kotlin.resolve.scopes.receivers.TypeAliasQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.TypeParameterQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.expression
-import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
-import org.jetbrains.kotlin.resolve.scopes.utils.findFirstFromMeAndParent
-import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
-import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
-import org.jetbrains.kotlin.synthetic.isVisibleOutside
-import org.jetbrains.kotlin.types.ErrorUtils
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.TypeConstructor
-import org.jetbrains.kotlin.types.TypeSubstitutor
-import org.jetbrains.kotlin.types.TypeUtils
-import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
-import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl
-import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
-import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
-import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
-import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
-import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
-import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
-import org.jetbrains.kotlin.types.typeUtil.isUnit
-import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
-import java.util.Locale
-
-/**
- * This class is used to resolve a KTX Element to the corresponding set of calls on the composer, and the individual calls for
- * each attribute, etc.
- */
-class ComposeEmitResolver(
-    callResolver: CallResolver,
-    project: Project,
-    private val composer: ComposerMetadata
-) {
-
-    private val callResolver = NoInterceptionCallResolver(callResolver)
-
-    private class TempParameterInfo(
-        val attribute: AttributeInfo,
-        val descriptor: DeclarationDescriptor
-    )
-
-    // NOTE(lmr): I am unsure of the performance consequences of using KtPsiFactory. it appears to create a file for every
-    // call, which seems like something we definitely do not want, but it's also used in resolving for(..) loops, so
-    // maybe it's not terrible.
-    private val psiFactory = KtPsiFactory(project, markGenerated = false)
-
-    private fun KotlinType.isEmittable() = composer.isEmittable(this)
-
-    private fun KotlinType.isCompoundEmittable() = composer.isCompoundEmittable(this)
-
-    private fun isImplicitConstructorParam(
-        param: ValueParameterDescriptor,
-        fn: CallableDescriptor
-    ) = composer.isImplicitConstructorParam(param, fn)
-
-    fun resolveCandidates(
-        call: Call,
-        candidates: Collection<FunctionDescriptor>,
-        name: Name,
-        resolutionContext: ResolutionContext<*>
-    ): List<ComposableEmitDescriptor> {
-        val context = ExpressionTypingContext.newContext(
-            resolutionContext.trace,
-            resolutionContext.scope,
-            resolutionContext.dataFlowInfo,
-            resolutionContext.expectedType,
-            resolutionContext.languageVersionSettings,
-            resolutionContext.dataFlowValueFactory
-        )
-        val openTagExpr = call.calleeExpression ?: error("Expected calleeExpression")
-
-        val tmpTraceAndCache = TemporaryTraceAndCache.create(
-            context,
-            "trace for ktx tag",
-            openTagExpr
-        )
-
-        val contextToUse = context.replaceTraceAndCache(tmpTraceAndCache)
-
-        val attrInfos = mutableMapOf<String, AttributeInfo>()
-
-        for (arg in call.valueArguments) {
-            if (arg is KtLambdaArgument) continue
-
-            // NOTE: emits *must* use all named parameters. If they don't, we will not resolve them.
-            val argName = arg.getArgumentName() ?: return emptyList()
-
-            val key = argName.referenceExpression
-            val value = arg.getArgumentExpression()
-            val identifier = argName.asName.asString()
-
-            // NOTE: We don't have to check for duplicate argument names, that will be done elsewhere.
-
-            // NOTE: We don't have to deal with punning. punning isn't supported in FCS.
-
-            attrInfos[identifier] = AttributeInfo(
-                value = value ?: error("expected a value expression"),
-                key = key,
-                name = identifier
-            )
-        }
-
-        for (arg in call.functionLiteralArguments) {
-            if (attrInfos.containsKey(CHILDREN_KEY))
-                error("Only one children argument supported at a time")
-            attrInfos[CHILDREN_KEY] =
-                AttributeInfo(
-                    value = arg.getLambdaExpression() ?: error("expected a value expression"),
-                    key = null,
-                    name = CHILDREN_KEY
-                )
-        }
-
-        val receiver = resolveReceiver(openTagExpr, contextToUse)
-
-        attrInfos[TAG_KEY] =
-            AttributeInfo(
-                value = when (receiver) {
-                    is ExpressionReceiver -> receiver.expression
-                    else -> openTagExpr
-                },
-                key = null,
-                name = TAG_KEY
-            )
-
-        val result = resolveChild(
-            openTagExpr,
-            candidates,
-            name,
-            makeCall(
-                callElement = call.callElement,
-                calleeExpression = call.calleeExpression,
-                receiver = call.explicitReceiver,
-                dispatchReceiver = call.dispatchReceiver
-            ),
-            attrInfos,
-            context
-        )
-
-        tmpTraceAndCache.commit()
-        return result
-    }
-
-    private fun resolveChild(
-        expression: KtExpression,
-        candidates: Collection<FunctionDescriptor>,
-        name: Name,
-        call: Call,
-        attributes: Map<String, AttributeInfo>,
-        context: ExpressionTypingContext
-    ): List<ComposableEmitDescriptor> {
-        return candidates
-            .mapNotNull { result ->
-            val tmpForCandidate = TemporaryTraceAndCache.create(
-                context, "trace to resolve ktx element", expression
-            )
-
-            val trace: BindingTrace = tmpForCandidate.trace
-
-            val candidateContext = context
-                .replaceTraceAndCache(tmpForCandidate)
-                .replaceBindingTrace(trace)
-
-            val attrsUsedInCall = mutableSetOf<String>()
-
-            val attrsUsedInSets = mutableSetOf<String>()
-
-            val subMissingRequiredAttributes = mutableListOf<DeclarationDescriptor>()
-
-            val usedAttributeInfos = mutableListOf<TempParameterInfo>()
-
-            val candidateResults = resolveCandidate(
-                result,
-                call,
-                attributes,
-                attrsUsedInCall,
-                usedAttributeInfos,
-                subMissingRequiredAttributes,
-                candidateContext
-            )
-
-            if (candidateResults.isNothing)
-                return@mapNotNull null
-
-            val resolvedCall = candidateResults.resultingCalls.first()
-
-            if (!candidateResults.isSuccess) {
-                when (candidateResults.resultCode) {
-                    OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH -> {
-                        resolvedCall.call.valueArguments.map {
-                            resolvedCall.getArgumentMapping(it)
-                        }.forEach {
-                            when (it) {
-                                is ArgumentMatch -> {
-                                    when (it.status) {
-                                        ArgumentMatchStatus.TYPE_MISMATCH -> {
-                                            return@forEach
-                                        }
-                                        ArgumentMatchStatus.MATCH_MODULO_UNINFERRED_TYPES -> {
-                                            return@forEach
-                                        }
-                                        ArgumentMatchStatus.UNKNOWN -> {
-                                            // NOTE(lmr): This can happen with the implicit constructor params. ignore it
-                                        }
-                                        ArgumentMatchStatus.SUCCESS -> {
-                                            // do nothing
-                                        }
-                                        ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE -> {
-                                            // NOTE(lmr): This can happen when the attribute has no value expression, since
-                                            // we pass in a fake psi node for the value in that case.
-                                        }
-                                    }
-                                }
-                                is ArgumentUnmapped -> {
-                                    return@mapNotNull null
-                                }
-                            }
-                        }
-                    }
-                    OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE,
-                    OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES,
-                    OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER -> {
-                        return@mapNotNull null
-                    }
-                    else -> {
-                        error("new kind of resolution problem. figure out why this happened...")
-                    }
-                }
-            }
-
-            if (
-                !descriptorsEqualWithSubstitution(
-                    resolvedCall.semanticCall.candidateDescriptor.original,
-                    result.original
-                )
-            ) {
-                // if this happens, we've likely resolved the candidate to one of the other candidates, and we don't want that.
-                // we fail in this case, since it will succeed once we actually process the candidate that this resolved to.
-                return@mapNotNull null
-            }
-
-            val returnType = resolvedCall.resultingDescriptor.returnType ?: builtIns.unitType
-
-            if (!returnType.isEmittable()) return@mapNotNull null
-
-            var hasChildren = false
-
-            val emitCall = resolveComposerEmit(
-                constructedType = returnType,
-                hasBody = attributes.contains(CHILDREN_KEY),
-                implicitCtorTypes = resolvedCall.call.valueArguments.mapNotNull {
-                    (it as? ImplicitCtorValueArgument)?.type
-                },
-                expressionToReportErrorsOn = expression,
-                context = candidateContext
-            ) ?: return@mapNotNull null
-
-            if (attributes.contains(CHILDREN_KEY) && returnType.isCompoundEmittable()) {
-                attrsUsedInSets.add(CHILDREN_KEY)
-                hasChildren = true
-            }
-
-            val updateReceiverScope = emitCall
-                .resultingDescriptor
-                .valueParameters
-                .first { it.name == KtxNameConventions.EMIT_UPDATER_PARAMETER }
-                .type
-                .getReceiverTypeFromFunctionType() ?: error("Expected receiver type")
-
-            val setterValidations = resolveAllSetAttributes(
-                expressionToReportErrorsOn = expression,
-                receiverScope = updateReceiverScope,
-                type = returnType,
-                attributes = attributes,
-                attributesUsedInCall = attrsUsedInCall,
-                consumedAttributes = attrsUsedInSets,
-                missingRequiredAttributes = subMissingRequiredAttributes,
-                context = candidateContext
-            )
-
-            val pivotals = resolvePivotalAttributes(
-                attributes,
-                attrsUsedInCall,
-                usedAttributeInfos,
-                setterValidations,
-                returnType
-            )
-
-            return@mapNotNull ComposableEmitDescriptor.build(
-                hasChildren = hasChildren,
-                ctorCall = resolvedCall,
-                validations = setterValidations,
-                pivotals = pivotals,
-                ctorParams = resolvedCall.buildParamsFromAttributes(attributes),
-                emitCall = emitCall,
-                name = name,
-                composerMetadata = composer
-            )
-        }
-    }
-
-    private fun resolvePivotalAttributes(
-        attributes: Map<String, AttributeInfo>,
-        attrsUsedInCall: Set<String>,
-        callParamInfos: List<TempParameterInfo>,
-        validations: List<ValidatedAssignment>,
-        returnType: KotlinType?
-    ): List<String> {
-        val result = mutableListOf<String>()
-
-        if (returnType == null || returnType.isUnit()) {
-            return emptyList()
-        }
-
-        val validationSet = validations.map { it.name }.toSet()
-
-        // if you were in the ctor call but not in the sets, you *have* to be pivotal
-        for (info in callParamInfos) {
-            if (validationSet.contains(info.attribute.name)) continue
-            attributes[info.attribute.name] ?: continue
-            result.add(info.attribute.name)
-        }
-
-        // There are additional cases where attributes can be pivotal:
-        //   1. It is annotated as @Pivotal
-        //   2. It is a `val` ctor parameter
-        for (assignment in validations) {
-            val name = assignment.name
-            val descriptor = assignment.descriptor
-
-            if (descriptor is PropertyDescriptor &&
-                attrsUsedInCall.contains(name) && !descriptor.isVar) {
-                result.add(name)
-                continue
-            }
-        }
-
-        return result
-    }
-
-    private fun ResolvedCall<*>.buildParamsFromAttributes(
-        attributes: Map<String, AttributeInfo>
-    ): List<String> {
-        val possbileChildrenParam = valueArguments.keys.possibleChildrenParameter
-        return valueArguments.mapNotNull { (param, value) ->
-            val name = param.name.asString()
-//            var type = param.type
-            var attr = attributes[name]
-
-            if (param == possbileChildrenParam && attr == null) {
-                val childrenAttr = attributes[CHILDREN_KEY]
-                if (childrenAttr != null) {
-                    attr = childrenAttr
-                }
-//                if (param.isComposableFromChildrenAnnotation()) {
-//                    type = type.makeComposable(module)
-//                }
-            }
-
-            if (value is DefaultValueArgument) {
-                return@mapNotNull null
-            }
-
-            if (attr == null && isImplicitConstructorParam(param, resultingDescriptor)) {
-                return@mapNotNull null
-//                ImplicitCtorValueNode(
-//                    name = name,
-//                    descriptor = param,
-//                    type = type
-//                )
-            }
-
-            if (attr == null) {
-                error("Couldn't find attribute but expected to. param=$param name=$name")
-            }
-
-            attr.name
-        }
-    }
-
-    private fun resolveAllSetAttributes(
-        expressionToReportErrorsOn: KtExpression,
-        receiverScope: KotlinType,
-        type: KotlinType?,
-        attributes: Map<String, AttributeInfo>,
-        attributesUsedInCall: Set<String>,
-        consumedAttributes: MutableSet<String>,
-        missingRequiredAttributes: MutableList<DeclarationDescriptor>,
-        context: ExpressionTypingContext
-    ): List<ValidatedAssignment> {
-        if (type == null) return emptyList()
-        val results = mutableListOf<ValidatedAssignment>()
-
-        val tempForAttributes = TemporaryTraceAndCache.create(
-            context, "temp for attributes", expressionToReportErrorsOn
-        )
-
-        val tempForValidations = TemporaryTraceAndCache.create(
-            context, "temp for validations", expressionToReportErrorsOn
-        )
-
-        for ((name, attribute) in attributes) {
-            if (name == TAG_KEY) continue
-            if (name == CHILDREN_KEY) {
-                continue
-            }
-            val keyExpr = attribute.key ?: error("key expected")
-
-            val expectedTypes = mutableListOf<KotlinType>()
-
-            var resolvedCall: ResolvedCall<*>? = null
-
-            // NOTE(lmr): A ktx element that has access (like it's a recursive call or a nested class) to the private property
-            // of the tag will be able to set it as an attribute...  I'm not sure if that'a s good thing or not, but unless we
-            // do something extra, that is indeed possible. Perhaps it's something we should look into.
-
-            if (resolvedCall == null) {
-                resolvedCall = resolveAttributeAsSetter(
-                    type,
-                    attribute.name,
-                    keyExpr,
-                    attribute.value,
-                    expectedTypes,
-                    context.replaceTraceAndCache(tempForAttributes)
-                )
-            }
-
-            if (resolvedCall == null) {
-                resolvedCall = resolveAttributeAsProperty(
-                    type,
-                    keyExpr,
-                    attribute.value,
-                    expectedTypes,
-                    context.replaceTraceAndCache(tempForAttributes)
-                )
-            }
-
-            if (resolvedCall != null) {
-
-                val validationType = when {
-                    attributesUsedInCall.contains(name) -> ValidationType.UPDATE
-                    else -> ValidationType.SET
-                }
-
-                val attrType = when (val descriptor = resolvedCall.resultingDescriptor) {
-                    is FunctionDescriptor -> descriptor.valueParameters.firstOrNull()?.type
-                    is PropertyDescriptor -> descriptor.type
-                    else -> null
-                } ?: continue
-
-                val (validationCall, uncheckedValidationCall, lambdaDescriptor) =
-                    resolveValidationCall(
-                        expressionToReportErrorsOn = expressionToReportErrorsOn,
-                        receiverScope = receiverScope,
-                        assignmentReceiverScope = type,
-                        validationType = validationType,
-                        attrType = attrType,
-                        context = context.replaceTraceAndCache(tempForValidations)
-                    )
-
-                results.add(
-                    ValidatedAssignment(
-                        validationType = validationType,
-                        assignment = resolvedCall,
-                        assignmentLambda = lambdaDescriptor,
-                        name = name,
-                        validationCall = validationCall,
-                        uncheckedValidationCall = uncheckedValidationCall,
-                        descriptor = resolvedCall.resultingDescriptor,
-                        type = attrType
-                    )
-                )
-                consumedAttributes.add(name)
-            }
-        }
-
-        if (!type.isUnit()) {
-            val cls = type.constructor.declarationDescriptor as? ClassDescriptor
-                ?: error("unexpected classifier descriptor")
-            val requiredAttributes = cls.unsubstitutedMemberScope
-                .getContributedDescriptors()
-                .mapNotNull { it as? PropertyDescriptor }
-                // NOTE(lmr): I think we should consider not marking lateinit properties as required. It would maybe align
-                // ourselves more with the language semantic of `lateinit`
-                .filter {
-                    it.isLateInit && it.visibility.isVisibleOutside() &&
-                            !Visibilities.isPrivate(it.visibility)
-                }
-
-            requiredAttributes
-                .filter { !consumedAttributes.contains(it.name.asString()) }
-                .ifNotEmpty { missingRequiredAttributes.addAll(this) }
-        }
-
-        tempForAttributes.commit()
-        tempForValidations.commit()
-        return results
-    }
-
-    private fun resolveAttributeAsSetter(
-        instanceType: KotlinType,
-        name: String,
-        keyExpr: KtReferenceExpression,
-        valueExpr: KtExpression,
-        expectedTypes: MutableCollection<KotlinType>,
-        context: ExpressionTypingContext
-    ): ResolvedCall<*>? {
-        val setterName = Name.identifier(
-            ComposeUtils.setterMethodFromPropertyName(
-                name
-            )
-        )
-        val receiver = TransientReceiver(instanceType)
-
-        val call = makeCall(
-            keyExpr,
-            calleeExpression = keyExpr,
-            valueArguments = listOf(CallMaker.makeValueArgument(valueExpr)),
-            receiver = receiver
-        )
-
-        val temporaryForFunction = TemporaryTraceAndCache.create(
-            context, "trace to resolve as function call", keyExpr
-        )
-
-        val results = callResolver.computeTasksAndResolveCall<FunctionDescriptor>(
-            BasicCallResolutionContext.create(
-                context.replaceTraceAndCache(temporaryForFunction),
-                call,
-                CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-                DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call)
-            ),
-            setterName,
-            keyExpr,
-            NewResolutionOldInference.ResolutionKind.Function
-        )
-
-        if (results.isNothing) {
-            return null
-        }
-
-        if (results.isAmbiguity || temporaryForFunction.trace.hasTypeMismatchErrorsOn(valueExpr)) {
-            expectedTypes.addAll(
-                results.resultingCalls.mapNotNull {
-                    it.resultingDescriptor.valueParameters.firstOrNull()
-                }.map { it.type }
-            )
-            return null
-        }
-
-        val resolvedCall = OverloadResolutionResultsUtil.getResultingCall(results, context)
-            ?: return null
-
-        temporaryForFunction.commit()
-
-        return resolvedCall
-    }
-
-    private fun resolveAttributeAsProperty(
-        instanceType: KotlinType,
-        keyExpr: KtSimpleNameExpression,
-        valueExpr: KtExpression,
-        expectedTypes: MutableCollection<KotlinType>,
-        context: ExpressionTypingContext
-    ): ResolvedCall<*>? {
-
-        // NOTE(lmr): I'm not sure what the consequences are of using the tagExpr as the receiver...
-        val receiver = TransientReceiver(instanceType)
-
-        val temporaryForVariable = TemporaryTraceAndCache.create(
-            context, "trace to resolve as local variable or property", keyExpr
-        )
-
-        val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-
-        val call = CallMaker.makePropertyCall(receiver, null, keyExpr)
-
-        val contextForVariable = BasicCallResolutionContext.create(
-            contextToUse,
-            call,
-            CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS
-        )
-
-        val results = callResolver.resolveSimpleProperty(contextForVariable)
-
-        if (results.isNothing) {
-            return null
-        }
-
-        val resolvedCall = OverloadResolutionResultsUtil.getResultingCall(results, contextToUse)
-            ?: return null
-
-        val descriptor = resolvedCall.resultingDescriptor as PropertyDescriptor
-        val expectedType = descriptor.type
-
-        if (temporaryForVariable.trace.hasTypeMismatchErrorsOn(valueExpr)) {
-            expectedTypes.add(expectedType)
-            return null
-        }
-
-        if (descriptor.setter == null) {
-            // NOTE(lmr): we probably shouldn't do this. if this ends up being a cross-module compile, then the
-            // setter will be gone. I'm not sure the right way to figure out whether or not a property is
-            // settable or not...
-            return null
-        }
-
-        temporaryForVariable.commit()
-
-        return resolvedCall
-    }
-
-    private fun resolveCandidate(
-        candidate: FunctionDescriptor,
-        original: Call,
-        attributes: Map<String, AttributeInfo>,
-        usedAttributes: MutableSet<String>,
-        usedAttributeInfos: MutableList<TempParameterInfo>,
-        missingRequiredAttributes: MutableList<DeclarationDescriptor>,
-        context: ExpressionTypingContext
-    ): OverloadResolutionResults<FunctionDescriptor> {
-        val valueArguments = mutableListOf<ValueArgument>()
-
-        val dispatchReceiver = original.dispatchReceiver
-
-        val stableParamNames = candidate.hasStableParameterNames()
-
-        val possibleChildrenParameter =
-            candidate.valueParameters.possibleChildrenParameter
-
-        for (param in candidate.valueParameters) {
-            val name = param.name.asString()
-            val attr = attributes[name]
-            var arg: ValueArgument? = null
-
-            if (arg == null && param == possibleChildrenParameter) {
-                val childrenAttr = attributes[CHILDREN_KEY]
-                if (childrenAttr != null) {
-                    usedAttributes.add(CHILDREN_KEY)
-
-                    usedAttributeInfos.add(
-                        TempParameterInfo(
-                            attribute = childrenAttr,
-                            descriptor = param
-                        )
-                    )
-
-                    arg = childrenAttr.toValueArgument(name, stableParamNames)
-                }
-            }
-
-            if (arg == null && attr != null) {
-                usedAttributes.add(name)
-                usedAttributeInfos.add(
-                    TempParameterInfo(
-                        attribute = attr,
-                        descriptor = param
-                    )
-                )
-                context.trace.record(BindingContext.REFERENCE_TARGET, attr.key, param)
-                arg = attr.toValueArgument(attr.name, stableParamNames)
-            }
-
-            if (arg == null && isImplicitConstructorParam(param, candidate)) {
-                arg = ImplicitCtorValueArgument(param.type)
-            }
-
-            if (arg != null) {
-                valueArguments.add(arg)
-            } else if (!param.declaresDefaultValue()) {
-                // missing required parameter!
-                if (
-                    dispatchReceiver?.type?.isExtensionFunctionType != true ||
-                    param != candidate.valueParameters[0]
-                ) {
-                    // if this isn't the case, the missing parameter is an extension parameter...
-                    // and it will be provided implicitly. We don't want to diagnose this as a
-                    // missing attribute. If it is missing, the call resolver will add a
-                    // diagnostic anyway.
-                    missingRequiredAttributes.add(param)
-                }
-            }
-        }
-
-        val call = makeCall(
-            original.callElement,
-            valueArguments = valueArguments,
-            calleeExpression = original.calleeExpression,
-            receiver = original.explicitReceiver,
-            dispatchReceiver = dispatchReceiver
-        )
-
-        val contextForVariable = BasicCallResolutionContext.create(
-            context,
-            call,
-            CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-            DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call)
-        )
-
-        return callResolver.resolveFunctionCall(contextForVariable)
-    }
-
-    private fun resolveReceiver(
-        expression: KtExpression,
-        context: ExpressionTypingContext
-    ): Receiver? {
-        if (expression !is KtQualifiedExpression) return null
-        val currentContext = context
-            .replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
-            .replaceContextDependency(ContextDependency.INDEPENDENT)
-
-        expression.elementChain(currentContext)
-
-        val receiverExpr = expression.receiverExpression
-
-        return context.trace.get(BindingContext.QUALIFIER, receiverExpr)
-            ?: ExpressionReceiver.create(
-                receiverExpr,
-                ErrorUtils.createErrorType("Type for " + receiverExpr.text),
-                context.trace.bindingContext
-            )
-    }
-
-    private fun makeValueArgument(
-        type: KotlinType,
-        context: ExpressionTypingContext,
-        forceType: Boolean = false
-    ): ValueArgument {
-        val fakeExpr = psiFactory.createSimpleName("tmpVar")
-
-        context.trace.record(
-            BindingContext.EXPRESSION_TYPE_INFO, fakeExpr, KotlinTypeInfo(
-                type = type,
-                dataFlowInfo = DataFlowInfo.EMPTY,
-                jumpOutPossible = false,
-                jumpFlowInfo = DataFlowInfo.EMPTY
-            )
-        )
-
-        if (forceType) {
-            context.trace.record(BindingContext.PROCESSED, fakeExpr, true)
-        }
-
-        return CallMaker.makeValueArgument(fakeExpr)
-    }
-
-    private fun resolveComposerEmit(
-        implicitCtorTypes: List<KotlinType>,
-        constructedType: KotlinType,
-        hasBody: Boolean,
-        expressionToReportErrorsOn: KtExpression,
-        context: ExpressionTypingContext
-    ): ResolvedCall<*>? {
-        return resolveSubstitutableComposerMethod(
-            KtxNameConventions.EMIT,
-            listOfNotNull(
-                builtIns.anyType,
-                functionType(
-                    parameterTypes = implicitCtorTypes,
-                    returnType = constructedType
-                ),
-                functionType(),
-                if (hasBody) functionType() else null
-            ),
-            constructedType,
-            expressionToReportErrorsOn,
-            context
-        )
-    }
-
-    private fun resolveSingleValidationCall(
-        expressionToReportErrorsOn: KtExpression,
-        receiverScope: KotlinType,
-        validationType: ValidationType,
-        checked: Boolean,
-        attrType: KotlinType,
-        lambdaArg: ValueArgument?,
-        context: ExpressionTypingContext
-    ): ResolvedCall<*>? {
-        val temporaryForVariable = TemporaryTraceAndCache.create(
-            context, "trace to resolve variable", expressionToReportErrorsOn
-        )
-        val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-        val name = validationType.name.toLowerCase(Locale.ROOT).let {
-            if (!checked) (it + "Unchecked") else it
-        }
-        val calleeExpression = psiFactory.createSimpleName(name)
-        val call = makeCall(
-            callElement = calleeExpression,
-            calleeExpression = calleeExpression,
-            valueArguments = listOfNotNull(
-                makeValueArgument(attrType, contextToUse, forceType = true),
-                lambdaArg
-            ),
-            receiver = TransientReceiver(receiverScope)
-        )
-        val results = callResolver.resolveCallWithGivenName(
-            BasicCallResolutionContext.create(
-                contextToUse,
-                call,
-                CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-                DataFlowInfoForArgumentsImpl(contextToUse.dataFlowInfo, call)
-            ),
-            call,
-            calleeExpression,
-            Name.identifier(name)
-        )
-
-        if (results.isSuccess) return results.resultingCall
-
-        if (results.resultCode == OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) {
-
-            // NOTE(lmr): We know the type of the attribute at this point, but it's possible for the validation call to require
-            // some help in order to do the type inference for the call. We are just guessing here that the type is going to be
-            // the attribute type, and not something more complicated. It is kind of a bummer that we need this and I wonder if
-            // there isn't a cleaner way to do this.
-
-            for (candidate in results.resultingCalls) {
-
-                val typeParam = candidate.typeArguments.keys.singleOrNull() ?: continue
-
-                if (!attrType.satisfiesConstraintsOf(typeParam)) continue
-
-                val nextTempTrace = TemporaryTraceAndCache.create(
-                    context, "trace to resolve variable", expressionToReportErrorsOn
-                )
-
-                val nextContext = context
-                    .replaceTraceAndCache(nextTempTrace)
-                    .replaceCollectAllCandidates(false)
-
-                val substitutor = TypeSubstitutor.create(
-                    mapOf(
-                        typeParam.typeConstructor to attrType.asTypeProjection()
-                    )
-                )
-
-                val nextCall = makeCall(
-                    callElement = expressionToReportErrorsOn,
-                    calleeExpression = calleeExpression,
-                    receiver = TransientReceiver(composer.type),
-                    valueArguments = candidate.candidateDescriptor.valueParameters.map {
-                        makeValueArgument(it.type, nextContext)
-                    }
-                )
-
-                val nextResults = callResolver.resolveCallWithKnownCandidate(
-                    nextCall,
-                    TracingStrategyImpl.create(calleeExpression, nextCall),
-                    BasicCallResolutionContext.create(
-                        nextContext,
-                        nextCall,
-                        CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-                        DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
-                    ),
-                    ResolutionCandidate.create(
-                        nextCall,
-                        candidate.candidateDescriptor,
-                        candidate.dispatchReceiver,
-                        candidate.explicitReceiverKind,
-                        substitutor
-                    ),
-                    DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
-                )
-
-                if (nextResults.isSuccess) {
-                    nextTempTrace.commit()
-                    return nextResults.resultingCall
-                }
-            }
-        }
-
-        return null
-    }
-
-    private fun resolveValidationCall(
-        expressionToReportErrorsOn: KtExpression,
-        receiverScope: KotlinType,
-        assignmentReceiverScope: KotlinType?,
-        validationType: ValidationType,
-        attrType: KotlinType,
-        context: ExpressionTypingContext
-    ): Triple<ResolvedCall<*>?, ResolvedCall<*>?, FunctionDescriptor?> {
-        val temporaryForVariable = TemporaryTraceAndCache.create(
-            context, "trace to resolve variable", expressionToReportErrorsOn
-        )
-        val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-
-        val includeLambda = validationType != ValidationType.CHANGED
-
-        // for call:
-        // ValidatorType.set(AttrType, (AttrType) -> Unit): Boolean
-        // ValidatorType.update(AttrType, (AttrType) -> Unit): Boolean
-        // ValidatorType.changed(AttrType): Boolean
-
-        // for emit:
-        // ValidatorType.set(AttrType, ElementType.(AttrType) -> Unit): Unit
-        // ValidatorType.update(AttrType, ElementType.(AttrType) -> Unit): Unit
-        // ValidatorType.changed(AttrType): Unit
-
-        val lambdaType = when {
-            includeLambda -> functionType(
-                parameterTypes = listOf(attrType),
-                receiverType = assignmentReceiverScope
-            )
-            else -> null
-        }
-        val lambdaArg = lambdaType?.let { makeValueArgument(it, contextToUse) }
-        val lambdaDescriptor = lambdaType?.let {
-            createFunctionDescriptor(
-                it,
-                contextToUse
-            )
-        }
-
-        val validationCall = resolveSingleValidationCall(
-            expressionToReportErrorsOn = expressionToReportErrorsOn,
-            receiverScope = receiverScope,
-            validationType = validationType,
-            checked = true,
-            attrType = attrType,
-            lambdaArg = lambdaArg,
-            context = context
-        )
-
-        val uncheckedValidationCall = resolveSingleValidationCall(
-            expressionToReportErrorsOn = expressionToReportErrorsOn,
-            receiverScope = receiverScope,
-            validationType = validationType,
-            checked = false,
-            attrType = attrType,
-            lambdaArg = lambdaArg,
-            context = context
-        )
-
-        return Triple(validationCall, uncheckedValidationCall, lambdaDescriptor)
-    }
-
-    private fun resolveSubstitutableComposerMethod(
-        methodName: Name,
-        argumentTypes: List<KotlinType>,
-        typeToSubstitute: KotlinType?,
-        expressionToReportErrorsOn: KtExpression,
-        context: ExpressionTypingContext
-    ): ResolvedCall<*>? {
-        val temporaryForVariable = TemporaryTraceAndCache.create(
-            context, "trace to resolve variable", expressionToReportErrorsOn
-        )
-        val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-
-        val composerExpr = psiFactory.createSimpleName(methodName.asString())
-
-        val call = makeCall(
-            callElement = expressionToReportErrorsOn,
-            calleeExpression = composerExpr,
-            receiver = TransientReceiver(composer.type),
-            valueArguments = argumentTypes.map { makeValueArgument(it, contextToUse) }
-        )
-
-        val results = callResolver.resolveCallWithGivenName(
-            BasicCallResolutionContext.create(
-                contextToUse,
-                call,
-                CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-                DataFlowInfoForArgumentsImpl(contextToUse.dataFlowInfo, call)
-            ),
-            call,
-            composerExpr,
-            methodName
-        )
-
-        if (results.isSuccess) return results.resultingCall
-
-        if (typeToSubstitute == null) return null
-
-        val candidates = if (context.collectAllCandidates)
-            results.allCandidates ?: emptyList()
-        else results.resultingCalls
-
-        for (candidate in candidates) {
-
-            val typeParam = candidate.candidateDescriptor.typeParameters.singleOrNull() ?: continue
-
-            if (!typeToSubstitute.satisfiesConstraintsOf(typeParam)) continue
-
-            val nextTempTrace = TemporaryTraceAndCache.create(
-                context, "trace to resolve variable", expressionToReportErrorsOn
-            )
-
-            val nextContext = context
-                .replaceTraceAndCache(nextTempTrace)
-                .replaceCollectAllCandidates(false)
-
-            val substitutor = TypeSubstitutor.create(
-                mapOf(
-                    typeParam.typeConstructor to typeToSubstitute.asTypeProjection()
-                )
-            )
-
-            val nextCall = makeCall(
-                callElement = expressionToReportErrorsOn,
-                calleeExpression = composerExpr,
-                receiver = TransientReceiver(composer.type),
-                valueArguments = candidate.candidateDescriptor.valueParameters.map {
-                    makeValueArgument(it.type, nextContext)
-                }
-            )
-
-            val nextResults = callResolver.resolveCallWithKnownCandidate(
-                nextCall,
-                TracingStrategyImpl.create(composerExpr, nextCall),
-                BasicCallResolutionContext.create(
-                    nextContext,
-                    nextCall,
-                    CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-                    DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
-                ),
-                ResolutionCandidate.create(
-                    nextCall,
-                    candidate.candidateDescriptor,
-                    candidate.dispatchReceiver,
-                    candidate.explicitReceiverKind,
-                    substitutor
-                ),
-                DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
-            )
-
-            if (nextResults.isSuccess) {
-                nextTempTrace.commit()
-                return nextResults.resultingCall
-            }
-        }
-
-        return if (context.collectAllCandidates) null
-        else resolveSubstitutableComposerMethod(
-            methodName,
-            argumentTypes,
-            typeToSubstitute,
-            expressionToReportErrorsOn,
-            context.replaceCollectAllCandidates(true)
-        )
-    }
-
-    private fun KtQualifiedExpression.elementChain(context: ExpressionTypingContext) {
-        val moduleDescriptor = context.scope.ownerDescriptor.module
-        val trace = context.trace
-        val scopeForFirstPart = context.scope
-
-        val path = asQualifierPartList()
-        val firstPart = path.first()
-        var currentDescriptor: DeclarationDescriptor? = scopeForFirstPart.findDescriptor(firstPart)
-        currentDescriptor =
-            currentDescriptor ?: moduleDescriptor.getPackage(FqName.topLevel(firstPart.name)).let {
-                if (it.isEmpty()) null else it
-            }
-
-        if (currentDescriptor == null) return
-        else storeSimpleNameExpression(firstPart.expression!!, currentDescriptor, trace)
-
-        // TODO(lmr): we need to add visibility checks into this function...
-        for (qualifierPartIndex in 1 until path.size) {
-            val qualifierPart = path[qualifierPartIndex]
-
-            val nextPackageOrClassDescriptor =
-                when (currentDescriptor) {
-                    // TODO(lmr): i wonder if we could allow this for Ktx. Seems like a nice to have
-                    // TODO type aliases as qualifiers? (would break some assumptions in TypeResolver)
-                    is TypeAliasDescriptor -> null
-                    is ClassDescriptor -> {
-                        var next: DeclarationDescriptor? = null
-                        next = next
-                            ?: currentDescriptor.unsubstitutedInnerClassesScope.findDescriptor(
-                                qualifierPart
-                            )
-                        if (currentDescriptor.kind == ClassKind.OBJECT) {
-                            next = next
-                                ?: currentDescriptor.unsubstitutedMemberScope.findDescriptor(
-                                    qualifierPart
-                                )
-                        }
-                        val cod = currentDescriptor.companionObjectDescriptor
-                        if (cod != null) {
-                            next = next
-                                ?: cod.unsubstitutedMemberScope.findDescriptor(qualifierPart)
-                        }
-                        next = next ?: currentDescriptor.staticScope.findDescriptor(qualifierPart)
-                        next
-                    }
-                    is PackageViewDescriptor -> {
-                        val packageView =
-                            if (qualifierPart.typeArguments == null) {
-                                moduleDescriptor.getPackage(
-                                    currentDescriptor.fqName.child(qualifierPart.name)
-                                )
-                            } else null
-                        if (packageView != null && !packageView.isEmpty()) {
-                            packageView
-                        } else {
-                            currentDescriptor.memberScope.findDescriptor(qualifierPart)
-                        }
-                    }
-                    is VariableDescriptor -> {
-                        currentDescriptor.type.memberScope.findDescriptor(qualifierPart)
-                    }
-                    else -> null
-                }
-
-            if (nextPackageOrClassDescriptor == null) return
-            else storeSimpleNameExpression(
-                qualifierPart.expression!!,
-                nextPackageOrClassDescriptor,
-                trace
-            )
-
-            currentDescriptor = nextPackageOrClassDescriptor
-        }
-    }
-
-    private fun storeSimpleNameExpression(
-        expression: KtSimpleNameExpression,
-        descriptor: DeclarationDescriptor,
-        trace: BindingTrace
-    ) {
-        trace.record(BindingContext.REFERENCE_TARGET, expression, descriptor)
-        UnderscoreUsageChecker.checkSimpleNameUsage(descriptor, expression, trace)
-
-        val qualifier = when (descriptor) {
-            is PackageViewDescriptor -> PackageQualifier(expression, descriptor)
-            is ClassDescriptor -> ClassQualifier(expression, descriptor)
-            is TypeParameterDescriptor -> TypeParameterQualifier(expression, descriptor)
-            is TypeAliasDescriptor -> descriptor.classDescriptor?.let {
-                TypeAliasQualifier(expression, descriptor, it)
-            }
-            else -> null
-        }
-
-        if (qualifier != null) {
-            trace.record(BindingContext.QUALIFIER, qualifier.expression, qualifier)
-        }
-    }
-}
-
-// general utils
-// ==============================
-
-private val builtIns = DefaultBuiltIns.Instance
-
-private fun functionType(
-    parameterTypes: List<KotlinType> = emptyList(),
-    annotations: Annotations = Annotations.EMPTY,
-    returnType: KotlinType = builtIns.unitType,
-    receiverType: KotlinType? = null
-): KotlinType = createFunctionType(
-    builtIns = builtIns,
-    annotations = annotations,
-    parameterNames = null,
-    parameterTypes = parameterTypes,
-    receiverType = receiverType,
-    returnType = returnType
-)
-
-private fun KotlinType.satisfiesConstraintsOf(T: TypeParameterDescriptor): Boolean {
-    return T.upperBounds.all { isSubtypeOf(it) }
-}
-
-// We want to return null in cases where types mismatch, so we use this heuristic to find out. I think there might be a more robust
-// way to find this out, but I'm not sure what it would be
-private fun BindingTrace.hasTypeMismatchErrorsOn(element: KtElement): Boolean =
-    bindingContext.diagnostics.forElement(element).any { it.severity == Severity.ERROR }
-
-private fun KtExpression.asQualifierPartList(): List<QualifiedExpressionResolver.QualifierPart> {
-    val result = SmartList<QualifiedExpressionResolver.QualifierPart>()
-
-    fun addQualifierPart(expression: KtExpression?): Boolean {
-        if (expression is KtSimpleNameExpression) {
-            result.add(
-                QualifiedExpressionResolver.ExpressionQualifierPart(
-                    expression.getReferencedNameAsName(),
-                    expression
-                )
-            )
-            return true
-        }
-        return false
-    }
-
-    var expression: KtExpression? = this
-    while (true) {
-        if (addQualifierPart(expression)) break
-        if (expression !is KtQualifiedExpression) break
-
-        addQualifierPart(expression.selectorExpression)
-
-        expression = expression.receiverExpression
-    }
-
-    return result.asReversed()
-}
-
-private fun HierarchicalScope.findDescriptor(
-    part: QualifiedExpressionResolver.QualifierPart
-): DeclarationDescriptor? {
-    return findFirstFromMeAndParent {
-        it.findVariable(part.name, part.location)
-            ?: it.findFunction(part.name, part.location)
-            ?: it.findClassifier(part.name, part.location)
-    }
-}
-
-private fun MemberScope.findDescriptor(
-    part: QualifiedExpressionResolver.QualifierPart
-): DeclarationDescriptor? {
-    return this.getContributedClassifier(part.name, part.location)
-        ?: getContributedFunctions(part.name, part.location).singleOrNull()
-        ?: getContributedVariables(part.name, part.location).singleOrNull()
-}
-
-private fun AttributeInfo.toValueArgument(name: String, named: Boolean): ValueArgument {
-    val argumentName = if (named) object : ValueArgumentName {
-        override val asName: Name
-            get() = Name.identifier(name)
-        override val referenceExpression: KtSimpleNameExpression?
-            get() = key
-    } else null
-    return object : ValueArgument {
-        override fun getArgumentExpression() = value
-        override fun getArgumentName() = argumentName
-        override fun isNamed() = named
-        override fun asElement(): KtElement = value
-        override fun getSpreadElement(): LeafPsiElement? = null
-        override fun isExternal() = true
-    }
-}
-
-/**
- * This function was copied verbatim from descriptorUtils.kt from ide-common.  For some reason, importing this method into our module
- * would not work and would cause a NoClassDefFound exception.
- */
-private fun descriptorsEqualWithSubstitution(
-    descriptor1: DeclarationDescriptor?,
-    descriptor2: DeclarationDescriptor?
-): Boolean {
-    if (descriptor1 == descriptor2) return true
-    if (descriptor1 == null || descriptor2 == null) return false
-    if (descriptor1 !is CallableDescriptor) return true
-    descriptor2 as CallableDescriptor
-
-    val typeChecker = KotlinTypeCheckerImpl.withAxioms(
-        object : KotlinTypeChecker.TypeConstructorEquality {
-            override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
-                val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor
-                val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor
-                if (typeParam1 != null && typeParam2 != null &&
-                    typeParam1.containingDeclaration == descriptor1 &&
-                    typeParam2.containingDeclaration == descriptor2
-                ) {
-                    return typeParam1.index == typeParam2.index
-                }
-
-                return a == b
-            }
-        }
-    )
-
-    if (!typeChecker.equalTypesOrNulls(descriptor1.returnType, descriptor2.returnType)) return false
-
-    val parameters1 = descriptor1.valueParameters
-    val parameters2 = descriptor2.valueParameters
-    if (parameters1.size != parameters2.size) return false
-    for ((param1, param2) in parameters1.zip(parameters2)) {
-        if (!typeChecker.equalTypes(param1.type, param2.type)) return false
-    }
-    // NOTE(lmr): edit
-    // this check was added
-    if (descriptor1.javaClass !== descriptor2.javaClass) return false
-    // NOTE(lmr): /end
-    return true
-}
-
-private val ResolvedCall<*>.semanticCall: ResolvedCall<*>
-    get() = when (this) {
-        is VariableAsFunctionResolvedCall -> variableCall
-        else -> this
-    }
-
-private val Collection<ValueParameterDescriptor>.possibleChildrenParameter:
-        ValueParameterDescriptor?
-    get() = maxBy { it.index }?.let { if (it.type.isFunctionType) it else null }
-
-// move these to naming conventions???
-const val CHILDREN_KEY = "<children>"
-const val TAG_KEY = "<tag>"
-
-fun makeCall(
-    callElement: KtElement,
-    calleeExpression: KtExpression? = null,
-    valueArguments: List<ValueArgument> = emptyList(),
-    receiver: Receiver? = null,
-    dispatchReceiver: ReceiverValue? = null
-): Call {
-    return object : Call {
-        override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
-        override fun getValueArgumentList(): KtValueArgumentList? = null
-        override fun getTypeArgumentList(): KtTypeArgumentList? = null
-        override fun getExplicitReceiver(): Receiver? = receiver
-        override fun getCalleeExpression(): KtExpression? = calleeExpression
-        override fun getValueArguments(): List<ValueArgument> = valueArguments
-        override fun getCallElement(): KtElement = callElement
-        override fun getFunctionLiteralArguments(): List<LambdaArgument> = emptyList()
-        override fun getTypeArguments(): List<KtTypeProjection> = emptyList()
-        override fun getCallType(): Call.CallType = Call.CallType.DEFAULT
-        override fun getCallOperationNode(): ASTNode? = null
-    }
-}
-
-fun createFunctionDescriptor(
-    type: KotlinType,
-    context: ExpressionTypingContext
-): FunctionDescriptor {
-    return AnonymousFunctionDescriptor(
-        context.scope.ownerDescriptor,
-        Annotations.EMPTY,
-        CallableMemberDescriptor.Kind.SYNTHESIZED,
-        SourceElement.NO_SOURCE,
-        false
-    ).apply {
-        initialize(
-            type.getReceiverTypeFromFunctionType()?.let {
-                DescriptorFactory.createExtensionReceiverParameterForCallable(
-                    this,
-                    it,
-                    Annotations.EMPTY)
-            },
-            null,
-            emptyList(),
-            type.getValueParameterTypesFromFunctionType().mapIndexed { i, t ->
-                ValueParameterDescriptorImpl(
-                    containingDeclaration = this,
-                    original = null,
-                    index = i,
-                    annotations = Annotations.EMPTY,
-                    name = t.type.extractParameterNameFromFunctionTypeArgument()
-                        ?: Name.identifier("p$i"),
-                    outType = t.type,
-                    declaresDefaultValue = false,
-                    isCrossinline = false,
-                    isNoinline = false,
-                    varargElementType = null,
-                    source = SourceElement.NO_SOURCE
-                )
-            },
-            type.getReturnTypeFromFunctionType(),
-            Modality.FINAL,
-            Visibilities.LOCAL,
-            null
-        )
-        isOperator = false
-        isInfix = false
-        isExternal = false
-        isInline = false
-        isTailrec = false
-        isSuspend = false
-        isExpect = false
-        isActual = false
-    }
-}
-
-fun KotlinType.satisfiesConstraintsOf(bounds: List<KotlinType>): Boolean {
-    return bounds.all { isSubtypeOf(it) }
-}
-
-fun KotlinType.upperBounds(): List<KotlinType> {
-    return if (isTypeParameter()) {
-        TypeUtils.getTypeParameterDescriptorOrNull(this)?.upperBounds ?: emptyList()
-    } else {
-        listOf(this)
-    }
-}
-
-// util classes
-// ========================
-class ImplicitCtorValueArgument(val type: KotlinType) : ValueArgument {
-    override fun getArgumentExpression(): KtExpression? = null
-    override fun getArgumentName(): ValueArgumentName? = null
-    override fun isNamed(): Boolean = false
-    override fun asElement(): KtElement = error("tried to get element")
-    override fun getSpreadElement(): LeafPsiElement? = null
-    override fun isExternal(): Boolean = true
-}
-
-class AttributeInfo(
-    val value: KtExpression,
-    val key: KtSimpleNameExpression?,
-    val name: String
-)
-
-class NoInterceptionCallResolver(private val callResolver: CallResolver) {
-    fun resolveCallWithGivenName(
-        context: ResolutionContext<*>,
-        call: Call,
-        functionReference: KtReferenceExpression,
-        name: Name
-    ): OverloadResolutionResults<FunctionDescriptor> {
-        context.trace.record(
-            ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-            call,
-            true
-        )
-        return callResolver.resolveCallWithGivenName(
-            context,
-            call,
-            functionReference,
-            name
-        )
-    }
-
-    fun resolveCallWithKnownCandidate(
-        call: Call,
-        tracing: TracingStrategy,
-        context: ResolutionContext<*>,
-        candidate: ResolutionCandidate<FunctionDescriptor>,
-        dataFlowInfoForArguments: MutableDataFlowInfoForArguments?
-    ): OverloadResolutionResults<FunctionDescriptor> {
-        context.trace.record(
-            ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-            call,
-            true
-        )
-        return callResolver.resolveCallWithKnownCandidate(
-            call,
-            tracing,
-            context,
-            candidate,
-            dataFlowInfoForArguments
-        )
-    }
-
-    fun resolveSimpleProperty(
-        context: BasicCallResolutionContext
-    ): OverloadResolutionResults<VariableDescriptor> {
-        return callResolver.resolveSimpleProperty(
-            context
-        )
-    }
-
-    fun resolveFunctionCall(
-        context: BasicCallResolutionContext
-    ): OverloadResolutionResults<FunctionDescriptor> {
-        context.trace.record(
-            ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-            context.call,
-            true
-        )
-        return callResolver.resolveFunctionCall(
-            context
-        )
-    }
-
-    fun <T : CallableDescriptor> computeTasksAndResolveCall(
-        context: BasicCallResolutionContext,
-        name: Name,
-        referenceExpression: KtReferenceExpression,
-        kind: NewResolutionOldInference.ResolutionKind
-    ): OverloadResolutionResults<T> {
-        context.trace.record(
-            ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
-            context.call,
-            true
-        )
-        return callResolver.computeTasksAndResolveCall(
-            context,
-            name,
-            referenceExpression,
-            kind
-        )
-    }
-}
\ 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 cf79cb31..856fcc4 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
@@ -37,18 +37,17 @@
     val Composable = ComposeUtils.composeFqName("Composable")
     val CurrentComposerIntrinsic = ComposeUtils.composeFqName("<get-currentComposer>")
     val ComposableContract = ComposeUtils.composeFqName("ComposableContract")
-    val restartableFunction = FqName.fromSegments(listOf(
+    val composableLambda = FqName.fromSegments(listOf(
         "androidx",
         "compose",
         "internal",
-        "restartableFunction"
+        "composableLambda"
     ))
     val remember = ComposeUtils.composeFqName("remember")
     val key = ComposeUtils.composeFqName("key")
     val StableMarker = ComposeUtils.composeFqName("StableMarker")
     val Stable = ComposeUtils.composeFqName("Stable")
     val Composer = ComposeUtils.composeFqName("Composer")
-    val Untracked = ComposeUtils.composeFqName("Untracked")
     val UiComposer = FqName.fromSegments(listOf("androidx", "ui", "node", "UiComposer"))
     val Package = FqName.fromSegments(listOf("androidx", "compose"))
     val Function0 = FqName.fromSegments(listOf("kotlin", "jvm", "functions", "Function0"))
@@ -87,8 +86,10 @@
     val contract = annotations.findAnnotation(ComposeFqNames.ComposableContract) ?: return null
     return contract.argumentValue("readonly")?.value as? Boolean
 }
-fun Annotated.hasUntrackedAnnotation(): Boolean =
-    annotations.findAnnotation(ComposeFqNames.Untracked) != null
+fun Annotated.composableTrackedContract(): Boolean? {
+    val contract = annotations.findAnnotation(ComposeFqNames.ComposableContract) ?: return null
+    return contract.argumentValue("tracked")?.value as? Boolean
+}
 
 internal val KotlinType.isSpecialType: Boolean get() =
     this === NO_EXPECTED_TYPE || this === UNIT_EXPECTED_TYPE
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt
index 0a8b850..741e114 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt
@@ -16,12 +16,10 @@
 
 package androidx.compose.plugins.kotlin
 
-import androidx.compose.plugins.kotlin.compiler.lower.ComposableCallTransformer
 import androidx.compose.plugins.kotlin.compiler.lower.ComposerIntrinsicTransformer
 import androidx.compose.plugins.kotlin.compiler.lower.ComposerLambdaMemoization
 import androidx.compose.plugins.kotlin.compiler.lower.ComposerParamTransformer
 import androidx.compose.plugins.kotlin.compiler.lower.ComposableFunctionBodyTransformer
-import androidx.compose.plugins.kotlin.compiler.lower.ComposeResolutionMetadataTransformer
 import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
 import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
 import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -43,10 +41,6 @@
         // create a symbol remapper to be used across all transforms
         val symbolRemapper = DeepCopySymbolRemapper()
 
-        // add metadata from the frontend onto IR Nodes so that the metadata will travel
-        // with the ir nodes as they transform and get copied
-        ComposeResolutionMetadataTransformer(pluginContext).lower(moduleFragment)
-
         // Memoize normal lambdas and wrap composable lambdas
         ComposerLambdaMemoization(pluginContext, symbolRemapper, bindingTrace).lower(moduleFragment)
 
@@ -72,12 +66,6 @@
         ).lower(moduleFragment)
 
         generateSymbols(pluginContext)
-
-        // transform composable calls and emits into their corresponding calls appealing
-        // to the composer
-        ComposableCallTransformer(pluginContext, symbolRemapper, bindingTrace).lower(moduleFragment)
-
-        generateSymbols(pluginContext)
     }
 }
 
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt
index 736511e..7e3e8b7 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt
@@ -16,19 +16,7 @@
 
 package androidx.compose.plugins.kotlin
 
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
-import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.psi.KtCallExpression
-import org.jetbrains.kotlin.psi.KtFunction
-import org.jetbrains.kotlin.psi.KtFunctionLiteral
-import org.jetbrains.kotlin.psi.KtLambdaArgument
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
-import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
 
 object ComposeUtils {
 
@@ -39,39 +27,4 @@
     fun composeInternalFqName(cname: String? = null) = FqName(
         "${generateComposePackageName()}.internal${cname?.let { ".$it"} ?: ""}"
     )
-
-    fun setterMethodFromPropertyName(name: String): String {
-        return "set${name[0].toUpperCase()}${name.slice(1 until name.length)}"
-    }
-
-    fun propertyNameFromSetterMethod(name: String): String {
-        return if (name.startsWith("set")) "${
-            name[3].toLowerCase()
-        }${name.slice(4 until name.length)}" else name
-    }
-
-    fun isSetterMethodName(name: String): Boolean {
-        // use !lower to capture non-alpha chars
-        return name.startsWith("set") && name.length > 3 && !name[3].isLowerCase()
-    }
-
-    fun isComposeComponent(descriptor: DeclarationDescriptor): Boolean {
-        if (descriptor !is ClassDescriptor) return false
-        val baseComponentDescriptor =
-            descriptor.module.findClassAcrossModuleDependencies(
-                ClassId.topLevel(
-                    FqName(ComposeUtils.generateComposePackageName() + ".Component")
-                )
-            ) ?: return false
-        return descriptor.isSubclassOf(baseComponentDescriptor)
-    }
-}
-
-fun KtFunction.isEmitInline(bindingContext: BindingContext): Boolean {
-    if (this !is KtFunctionLiteral) return false
-    if (parent?.parent !is KtLambdaArgument) return false
-    val call = parent?.parent?.parent as? KtCallExpression
-    val resolvedCall = call?.getResolvedCall(bindingContext)
-    return resolvedCall != null &&
-            resolvedCall.candidateDescriptor is ComposableEmitDescriptor
 }
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposerMetadata.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposerMetadata.kt
deleted file mode 100644
index 9842f72..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposerMetadata.kt
+++ /dev/null
@@ -1,212 +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.plugins.kotlin
-
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
-import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
-import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi.KtPsiFactory
-import org.jetbrains.kotlin.resolve.calls.CallResolver
-import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
-import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
-import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.isError
-import org.jetbrains.kotlin.types.typeUtil.isNothingOrNullableNothing
-import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
-
-class ComposerMetadata(
-    val type: KotlinType,
-    // Set of valid upper bound types that were defined on the composer that can't have children
-    // For android, this should be [View]
-    private val emitSimpleUpperBoundTypes: Set<KotlinType>,
-    // Set of valid upper bound types that were defined on the composer that can have children.
-    // For android, this would be [ViewGroup]
-    private val emitCompoundUpperBoundTypes: Set<KotlinType>,
-    // The specification for `emit` on a composer allows for the `ctor` parameter to be a function type
-    // with any number of parameters. We allow for these parameters to be used as parameters in the
-    // Constructors that are emitted with a KTX tag. These parameters can be overridden with attributes
-    // in the KTX tag, but if there are required parameters with a type that matches one declared in the
-    // ctor parameter, we will resolve it automatically with the value passed in the `ctor` lambda.
-    //
-    // In order to do this resolution, we store a list of pairs of "upper bounds" to parameter types. For example,
-    // the following emit call:
-    //
-    //      fun <T : View> emit(key: Any, ctor: (context: Context) -> T, update: U<T>.() -> Unit)
-    //
-    // would produce a Pair of [View] to [Context]
-    private val emittableTypeToImplicitCtorTypes: List<Pair<List<KotlinType>, Set<KotlinType>>>
-) {
-
-    companion object {
-        private fun resolveComposerMethodCandidates(
-            name: Name,
-            context: BasicCallResolutionContext,
-            composerType: KotlinType,
-            callResolver: CallResolver,
-            psiFactory: KtPsiFactory
-        ): Collection<ResolvedCall<*>> {
-            val calleeExpression = psiFactory.createSimpleName(name.asString())
-
-            val methodCall = makeCall(
-                callElement = context.call.callElement,
-                calleeExpression = calleeExpression,
-                receiver = TransientReceiver(
-                    composerType
-                )
-            )
-
-            val contextForVariable =
-                BasicCallResolutionContext.create(
-                    context,
-                    methodCall,
-                    CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
-                    DataFlowInfoForArgumentsImpl(
-                        context.dataFlowInfo,
-                        methodCall
-                    )
-                )
-
-            val results = callResolver.resolveCallWithGivenName(
-                // it's important that we use "collectAllCandidates" so that extension functions get included
-                contextForVariable.replaceCollectAllCandidates(true),
-                methodCall,
-                calleeExpression,
-                name
-            )
-
-            return results.allCandidates ?: emptyList()
-        }
-
-        fun build(
-            composerType: KotlinType,
-            callResolver: CallResolver,
-            psiFactory: KtPsiFactory,
-            resolutionContext: BasicCallResolutionContext
-        ): ComposerMetadata {
-            val emitSimpleUpperBoundTypes = mutableSetOf<KotlinType>()
-            val emitCompoundUpperBoundTypes = mutableSetOf<KotlinType>()
-            val emittableTypeToImplicitCtorTypes =
-                mutableListOf<Pair<List<KotlinType>, Set<KotlinType>>>()
-
-            val emitCandidates = resolveComposerMethodCandidates(
-                KtxNameConventions.EMIT,
-                resolutionContext,
-                composerType,
-                callResolver,
-                psiFactory
-            )
-
-            for (candidate in emitCandidates.map { it.candidateDescriptor }) {
-                if (candidate.name != KtxNameConventions.EMIT) continue
-                if (candidate !is SimpleFunctionDescriptor) continue
-                val params = candidate.valueParameters
-                // NOTE(lmr): we could report diagnostics on some of these? it seems strange to emit diagnostics about a function
-                // that is not necessarily being used though. I think it's probably better to just ignore them here.
-
-                // the signature of emit that we are looking for has 3 or 4 parameters
-                if (params.size < 3 || params.size > 4) continue
-                val ctorParam = params.find {
-                    it.name == KtxNameConventions.EMIT_CTOR_PARAMETER
-                } ?: continue
-                if (!ctorParam.type.isFunctionTypeOrSubtype) continue
-
-                // the return type from the ctor param is the "upper bound" of the node type. It will often be a generic type with constraints.
-                val upperBounds = ctorParam.type.getReturnTypeFromFunctionType().upperBounds()
-
-                // the ctor param can have parameters itself, which we interpret as implicit parameter types that the composer knows how to
-                // automatically provide to the component. In the case of Android Views, this is how we automatically provide Context.
-                val implicitParamTypes =
-                    ctorParam.type.getValueParameterTypesFromFunctionType().map {
-                        it.type
-                    }
-
-                for (implicitType in implicitParamTypes) {
-                    emittableTypeToImplicitCtorTypes.add(upperBounds to implicitParamTypes.toSet())
-                }
-
-                emitSimpleUpperBoundTypes.addAll(upperBounds)
-
-                if (params.any { it.name == KtxNameConventions.EMIT_CHILDREN_PARAMETER }) {
-                    emitCompoundUpperBoundTypes.addAll(upperBounds)
-                }
-            }
-
-            return ComposerMetadata(
-                composerType,
-                emitSimpleUpperBoundTypes,
-                emitCompoundUpperBoundTypes,
-                emittableTypeToImplicitCtorTypes
-            )
-        }
-
-        fun getOrBuild(
-            composerType: KotlinType,
-            callResolver: CallResolver,
-            psiFactory: KtPsiFactory,
-            resolutionContext: BasicCallResolutionContext
-        ): ComposerMetadata {
-            val meta = resolutionContext.trace.bindingContext[
-                    ComposeWritableSlices.COMPOSER_METADATA,
-                    composerType
-            ]
-            return if (meta == null) {
-                val built = build(composerType, callResolver, psiFactory, resolutionContext)
-                resolutionContext.trace.record(
-                    ComposeWritableSlices.COMPOSER_METADATA,
-                    composerType,
-                    built
-                )
-                built
-            } else {
-                meta
-            }
-        }
-    }
-
-    fun isEmittable(type: KotlinType) =
-        !type.isError && !type.isNothingOrNullableNothing() && emitSimpleUpperBoundTypes.any {
-            type.isSubtypeOf(it)
-        }
-
-    fun isCompoundEmittable(type: KotlinType) = !type.isError &&
-            !type.isNothingOrNullableNothing() &&
-            emitCompoundUpperBoundTypes.any {
-                type.isSubtypeOf(it)
-            }
-
-    fun isImplicitConstructorParam(
-        param: ValueParameterDescriptor,
-        fn: CallableDescriptor
-    ): Boolean {
-        val returnType = fn.returnType ?: return false
-        val paramType = param.type
-        for ((upperBounds, implicitTypes) in emittableTypeToImplicitCtorTypes) {
-            if (!implicitTypes.any { it.isSubtypeOf(paramType) }) continue
-            if (!returnType.satisfiesConstraintsOf(upperBounds)) continue
-            return true
-        }
-        return false
-    }
-}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt
index ffb71c6..b306a6f 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt
@@ -8,19 +8,8 @@
     val KEY_PARAMETER = Name.identifier("\$key")
     val CHANGED_PARAMETER = Name.identifier("\$changed")
     val DEFAULT_PARAMETER = Name.identifier("\$default")
-    val EMIT = Name.identifier("emit")
     val JOINKEY = Name.identifier("joinKey")
     val STARTRESTARTGROUP = Name.identifier("startRestartGroup")
     val ENDRESTARTGROUP = Name.identifier("endRestartGroup")
     val UPDATE_SCOPE = Name.identifier("updateScope")
-
-    val EMIT_KEY_PARAMETER = Name.identifier("key")
-    val EMIT_CTOR_PARAMETER = Name.identifier("ctor")
-    val EMIT_UPDATER_PARAMETER = Name.identifier("update")
-    val EMIT_CHILDREN_PARAMETER = Name.identifier("children")
-
-    val CALL_KEY_PARAMETER = Name.identifier("key")
-    val CALL_CTOR_PARAMETER = Name.identifier("ctor")
-    val CALL_INVALID_PARAMETER = Name.identifier("invalid")
-    val CALL_BLOCK_PARAMETER = Name.identifier("block")
 }
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt
index 20e9f8e..ca4d395 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt
@@ -2,46 +2,22 @@
 
 import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
 import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
-import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer
-import org.jetbrains.kotlin.diagnostics.rendering.Renderers
 import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_COLLECTION_OF_TYPES
-import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
 
 object ComposeDefaultErrorMessages : DefaultErrorMessages.Extension {
     private val MAP = DiagnosticFactoryToRendererMap("Compose")
     override fun getMap() = MAP
 
-    val OUR_STRING_RENDERER = object : DiagnosticParameterRenderer<String> {
-        override fun render(obj: String, renderingContext: RenderingContext): String {
-            return obj
-        }
-    }
-
     init {
         MAP.put(
-            ComposeErrors.NO_COMPOSER_FOUND,
-            "Couldn't find a valid composer."
-        )
-        MAP.put(
             ComposeErrors.OPEN_MODEL,
             "Model objects cannot be open or abstract"
         )
         MAP.put(
-            ComposeErrors.INVALID_COMPOSER_IMPLEMENTATION,
-            "Composer of type ''{0}'' was found to be an invalid Composer implementation. " +
-                    "Reason: {1}",
-            Renderers.RENDER_TYPE,
-            OUR_STRING_RENDERER
-        )
-        MAP.put(
             ComposeErrors.SUSPEND_FUNCTION_USED_AS_SFC,
             "Suspend functions are not allowed to be used as Components"
         )
         MAP.put(
-            ComposeErrors.INVALID_TYPE_SIGNATURE_SFC,
-            "Only Unit-returning functions are allowed to be used as Components"
-        )
-        MAP.put(
             ComposeErrors.COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,
             "Functions which invoke @Composable functions must be marked with the @Composable " +
                     "annotation"
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java
index c4c4d9f..b7ab4aa7 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java
@@ -37,12 +37,6 @@
             SUSPEND_FUNCTION_USED_AS_SFC = DiagnosticFactory0.create(ERROR);
     DiagnosticFactory0<PsiElement>
             COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE = DiagnosticFactory0.create(ERROR);
-    DiagnosticFactory0<KtElement>
-            INVALID_TYPE_SIGNATURE_SFC = DiagnosticFactory0.create(ERROR);
-    DiagnosticFactory0<KtElement>
-            NO_COMPOSER_FOUND = DiagnosticFactory0.create(ERROR);
-    DiagnosticFactory2<KtElement, KotlinType, String>
-            INVALID_COMPOSER_IMPLEMENTATION = DiagnosticFactory2.create(ERROR);
     DiagnosticFactory2<KtExpression, Collection<KotlinType>, Collection<KotlinType>>
             ILLEGAL_ASSIGN_TO_UNIONTYPE = DiagnosticFactory2.create(ERROR);
     DiagnosticFactory0<PsiElement>
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt
index 7fdfad4..b0edb3e 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt
@@ -1,12 +1,9 @@
 package androidx.compose.plugins.kotlin.analysis
 
 import androidx.compose.plugins.kotlin.ComposableAnnotationChecker
-import androidx.compose.plugins.kotlin.ComposableEmitMetadata
-import androidx.compose.plugins.kotlin.ComposerMetadata
 import org.jetbrains.kotlin.descriptors.FunctionDescriptor
 import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
 import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
-import org.jetbrains.kotlin.psi.Call
 import org.jetbrains.kotlin.psi.KtElement
 import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice
 import org.jetbrains.kotlin.util.slicedMap.RewritePolicy
@@ -22,16 +19,8 @@
         BasicWritableSlice(RewritePolicy.DO_NOTHING)
     val STABLE_TYPE: WritableSlice<KotlinType, Boolean?> =
         BasicWritableSlice(RewritePolicy.DO_NOTHING)
-    val COMPOSER_METADATA: WritableSlice<KotlinType, ComposerMetadata> =
-        BasicWritableSlice(RewritePolicy.DO_NOTHING)
-    val IGNORE_COMPOSABLE_INTERCEPTION: WritableSlice<Call, Boolean> =
-        BasicWritableSlice(RewritePolicy.DO_NOTHING)
-    val COMPOSABLE_EMIT_METADATA: WritableSlice<IrAttributeContainer, ComposableEmitMetadata> =
-        BasicWritableSlice(RewritePolicy.DO_NOTHING)
     val IS_COMPOSABLE_CALL: WritableSlice<IrAttributeContainer, Boolean> =
         BasicWritableSlice(RewritePolicy.DO_NOTHING)
-    val IS_INLINE_COMPOSABLE_CALL: WritableSlice<IrAttributeContainer, Boolean> =
-        BasicWritableSlice(RewritePolicy.DO_NOTHING)
     val IS_SYNTHETIC_COMPOSABLE_CALL: WritableSlice<IrFunctionAccessExpression, Boolean> =
         BasicWritableSlice(RewritePolicy.DO_NOTHING)
 }
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 055d52e..e8384da 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
@@ -21,7 +21,6 @@
 import androidx.compose.plugins.kotlin.KtxNameConventions
 import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
 import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
 import androidx.compose.plugins.kotlin.isMarkedStable
 import androidx.compose.plugins.kotlin.isSpecialType
 import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
@@ -304,9 +303,6 @@
                     )
                 )
                     return true
-                if (it.isEmitInline(context.bindingContext)) {
-                    return true
-                }
             }
         }
         return false
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt
deleted file mode 100644
index 1f94017..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt
+++ /dev/null
@@ -1,443 +0,0 @@
-package androidx.compose.plugins.kotlin.compiler.lower
-
-import androidx.compose.plugins.kotlin.ComposableEmitMetadata
-import androidx.compose.plugins.kotlin.EmitChildrenValueParameterDescriptor
-import androidx.compose.plugins.kotlin.KtxNameConventions
-import androidx.compose.plugins.kotlin.ValidatedAssignment
-import androidx.compose.plugins.kotlin.ValidationType
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.irTrace
-import org.jetbrains.kotlin.backend.common.FileLoweringPass
-import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
-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.descriptors.ClassConstructorDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.ir.IrStatement
-import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
-import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
-import org.jetbrains.kotlin.ir.builders.irBlock
-import org.jetbrains.kotlin.ir.builders.irCall
-import org.jetbrains.kotlin.ir.builders.irGet
-import org.jetbrains.kotlin.ir.builders.irInt
-import org.jetbrains.kotlin.ir.builders.irReturn
-import org.jetbrains.kotlin.ir.builders.irReturnUnit
-import org.jetbrains.kotlin.ir.builders.irTemporary
-import org.jetbrains.kotlin.ir.declarations.IrDeclaration
-import org.jetbrains.kotlin.ir.declarations.IrFile
-import org.jetbrains.kotlin.ir.declarations.IrFunction
-import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
-import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
-import org.jetbrains.kotlin.ir.declarations.IrValueParameter
-import org.jetbrains.kotlin.ir.declarations.getIrValueParameter
-import org.jetbrains.kotlin.ir.expressions.IrCall
-import org.jetbrains.kotlin.ir.expressions.IrConst
-import org.jetbrains.kotlin.ir.expressions.IrExpression
-import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
-import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
-import org.jetbrains.kotlin.ir.expressions.getValueArgument
-import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
-import org.jetbrains.kotlin.ir.expressions.putTypeArguments
-import org.jetbrains.kotlin.ir.expressions.putValueArgument
-import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
-import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi2ir.findFirstFunction
-import org.jetbrains.kotlin.resolve.BindingTrace
-import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
-import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
-
-class ComposableCallTransformer(
-    context: IrPluginContext,
-    symbolRemapper: DeepCopySymbolRemapper,
-    bindingTrace: BindingTrace
-) :
-    AbstractComposeLowering(context, symbolRemapper, bindingTrace),
-    FileLoweringPass,
-    ModuleLoweringPass {
-
-    override fun lower(module: IrModuleFragment) {
-        module.transformChildrenVoid(this)
-    }
-
-    override fun lower(irFile: IrFile) {
-        irFile.transformChildrenVoid(this)
-    }
-
-    private val declarationStack = mutableListOf<IrSymbolOwner>()
-
-    override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
-        if (declaration !is IrSymbolOwner) return super.visitDeclaration(declaration)
-        try {
-            declarationStack.push(declaration)
-            return super.visitDeclaration(declaration)
-        } finally {
-            declarationStack.pop()
-        }
-    }
-
-    override fun visitCall(expression: IrCall): IrExpression {
-        val emitMetadata = context.irTrace[
-                ComposeWritableSlices.COMPOSABLE_EMIT_METADATA,
-                expression
-        ]
-        if (emitMetadata != null) {
-            return DeclarationIrBuilder(context, declarationStack.last().symbol).irBlock {
-                +irComposableEmit(expression.transformChildren(), emitMetadata)
-            }
-        }
-        return super.visitCall(expression)
-    }
-
-    override fun visitFunctionExpression(expression: IrFunctionExpression): IrExpression {
-        if (expression.origin == IrStatementOrigin.LAMBDA) {
-            if (expression.function.valueParameters.lastOrNull()?.isComposerParam() == true) {
-                return DeclarationIrBuilder(context, declarationStack.last().symbol).irBlock {
-                    +expression.transformChildren()
-                }
-            }
-        }
-        return super.visitFunctionExpression(expression)
-    }
-
-    private fun isChildrenParameter(desc: ValueParameterDescriptor, expr: IrExpression): Boolean {
-        return expr is IrFunctionExpression &&
-                expr.origin == IrStatementOrigin.LAMBDA &&
-                desc is EmitChildrenValueParameterDescriptor
-    }
-
-    private fun IrBlockBuilder.getParameterExpression(
-        desc: ValueParameterDescriptor,
-        expr: IrExpression?
-    ): () -> IrExpression? {
-        if (expr == null)
-            return { null }
-        return when {
-            expr is IrConst<*> ->
-                ({ expr.copy() })
-            isChildrenParameter(desc, expr) ->
-                ({ expr })
-            else -> {
-                val temp = irTemporary(
-                    value = expr,
-                    irType = expr.type
-                )
-                ({ irGet(temp) })
-            }
-        }
-    }
-
-    private fun nearestComposer(): IrValueParameter {
-        for (fn in declarationStack.asReversed()) {
-            if (fn is IrFunction) {
-                val param = fn.composerParam()
-                if (param != null) {
-                    return param
-                }
-            }
-        }
-        error("Couldn't find composer parameter")
-    }
-
-    private fun IrBlockBuilder.irComposableEmit(
-        original: IrCall,
-        emitMetadata: ComposableEmitMetadata
-    ): IrExpression {
-        val composerParam = nearestComposer()
-        return irComposableEmitBase(
-            original,
-            { irGet(composerParam) },
-            emitMetadata
-        )
-    }
-
-    private fun IrBlockBuilder.irComposableEmitBase(
-        original: IrCall,
-        getComposer: () -> IrExpression,
-        emitMetadata: ComposableEmitMetadata
-    ): IrExpression {
-        /*
-
-        TextView(text="foo")
-
-        // transforms into
-
-        val attr_text = "foo"
-        composer.emit(
-            key = 123,
-            ctor = { context -> TextView(context) },
-            update = { set(attr_text) { text -> this.text = text } }
-        )
-         */
-        val parametersByName = original
-            .symbol
-            .descriptor
-            .valueParameters
-            .mapNotNull { desc ->
-                original.getValueArgument(desc)?.let { desc to it }
-            }
-            .map { (desc, expr) ->
-                desc.name.asString() to getParameterExpression(desc, expr)
-            }
-            .toMap()
-
-        val emitCall = emitMetadata.emitCall
-        val emitFunctionDescriptor = emitCall.candidateDescriptor
-
-        val emitParameters = emitFunctionDescriptor.valueParameters
-            .map { it.name to it }
-            .toMap()
-
-        fun getEmitParameter(name: Name) = emitParameters[name]
-            ?: error("Expected $name parameter to exist")
-
-        val emitFunctionSymbol = referenceFunction(emitFunctionDescriptor)
-
-        val joinKeyDescriptor = composerTypeDescriptor
-            .unsubstitutedMemberScope
-            .findFirstFunction(KtxNameConventions.JOINKEY.identifier) {
-                it.valueParameters.size == 2
-            }
-
-        fun irGetParameter(name: String): IrExpression = parametersByName[name]?.invoke()
-            ?: error("No parameter found with name $name")
-
-        return irCall(
-            callee = emitFunctionSymbol,
-            type = builtIns.unitType
-        ).apply {
-            dispatchReceiver = getComposer()
-            // TODO(lmr): extensionReceiver.
-            // We would want to do this to enable "emit" and "call" implementations that are
-            // extensions on the composer
-
-            putTypeArguments(emitCall.typeArguments) { it.toIrType() }
-
-            putValueArgument(
-                getEmitParameter(KtxNameConventions.EMIT_KEY_PARAMETER),
-                irGroupKey(
-                    original = original,
-                    getComposer = getComposer,
-                    joinKey = joinKeyDescriptor,
-                    pivotals = emitMetadata.pivotals.map { irGetParameter(it) }
-                )
-            )
-
-            val ctorParam = getEmitParameter(KtxNameConventions.EMIT_CTOR_PARAMETER)
-
-            val ctorLambdaDescriptor = createFunctionDescriptor(ctorParam.type)
-
-            putValueArgument(
-                ctorParam,
-                irLambdaExpression(
-                    original.startOffset,
-                    original.endOffset,
-                    descriptor = ctorLambdaDescriptor,
-                    type = ctorParam.type.toIrType()
-                ) { fn ->
-
-                    val ctorCall = emitMetadata.ctorCall
-
-                    val ctorCallSymbol = referenceConstructor(
-                        ctorCall.candidateDescriptor as ClassConstructorDescriptor
-                    )
-
-                    +irReturn(IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset,
-                        ctorCall.candidateDescriptor.returnType!!.toIrType(), ctorCallSymbol)
-                        .apply {
-                        putTypeArguments(ctorCall.typeArguments) { it.toIrType() }
-                        ctorLambdaDescriptor.valueParameters.zip(
-                            ctorCall
-                                .candidateDescriptor!!
-                                .valueParameters
-                        ) { a, b ->
-                            putValueArgument(
-                                b,
-                                irGet(fn.getIrValueParameter(a))
-                            )
-                        }
-                        emitMetadata.ctorParams.forEach { name ->
-                            val param = ctorCall
-                                .candidateDescriptor
-                                .valueParameters
-                                .firstOrNull { it.name.identifier == name }
-                            if (param != null) {
-                                putValueArgument(
-                                    param,
-                                    irGetParameter(name)
-                                )
-                            }
-                        }
-                    })
-                }
-            )
-
-            val updateParam = getEmitParameter(
-                KtxNameConventions
-                    .EMIT_UPDATER_PARAMETER
-            )
-
-            val updateLambdaDescriptor = createFunctionDescriptor(updateParam.type)
-
-            putValueArgument(
-                updateParam,
-                irLambdaExpression(
-                    original.startOffset,
-                    original.endOffset,
-                    descriptor = updateLambdaDescriptor,
-                    type = updateParam.type.toIrType()
-                ) { fn ->
-                    emitMetadata.validations.forEach {
-                        // set(attr_text) { text -> this.text = text }
-                        val arg = irGetParameter(it.name)
-                        +irValidatedAssignment(
-                            arg.startOffset,
-                            arg.endOffset,
-                            memoizing = true,
-                            validation = it,
-                            receiver = irGet(fn.extensionReceiverParameter!!),
-                            attributeValue = arg
-                        )
-                    }
-                    +irReturnUnit()
-                }
-            )
-
-            if (emitMetadata.hasChildren) {
-                val bodyParam = getEmitParameter(KtxNameConventions.EMIT_CHILDREN_PARAMETER)
-
-                val childrenExpr = irGetParameter("\$CHILDREN")
-
-                putValueArgument(
-                    bodyParam,
-                    childrenExpr
-                )
-            }
-        }
-    }
-
-    private fun IrBuilderWithScope.irGroupKey(
-        original: IrCall,
-        joinKey: FunctionDescriptor,
-        getComposer: () -> IrExpression,
-        pivotals: List<IrExpression>
-    ): IrExpression {
-        val keyValueExpression = irInt(original.sourceLocationHash())
-        return if (pivotals.isEmpty()) keyValueExpression
-        else (listOf(keyValueExpression) + pivotals).reduce { accumulator, value ->
-            irCall(
-                callee = referenceFunction(joinKey),
-                type = joinKey.returnType!!.toIrType()
-            ).apply {
-                dispatchReceiver = getComposer()
-                putValueArgument(0, accumulator)
-                putValueArgument(1, value)
-            }
-        }
-    }
-
-    private fun IrCall.sourceLocationHash(): Int {
-        return symbol.descriptor.fqNameSafe.toString().hashCode() xor startOffset
-    }
-
-    private fun IrBuilderWithScope.irValidatedAssignment(
-        startOffset: Int,
-        endOffset: Int,
-        memoizing: Boolean,
-        validation: ValidatedAssignment,
-        receiver: IrExpression,
-        attributeValue: IrExpression
-    ): IrExpression {
-        // for emit, fnDescriptor is Validator.(Value) -> Unit    or Validator.(Value, Element.(Value) -> Unit) -> Unit
-        // for call, fnDescriptor is Validator.(Value) -> Boolean or Validator.(Value, (Value) -> Unit) -> Boolean
-
-        // in emit, the element is passed through an extension parameter
-        // in call, the element is passed through a capture scope
-        val validationCall =
-            if (memoizing) validation.validationCall
-            else validation.uncheckedValidationCall
-
-        if (validationCall == null) error("Expected validationCall to be non-null")
-
-        val validationCallDescriptor = validationCall.candidateDescriptor as FunctionDescriptor
-
-        return irCall(
-            callee = referenceFunction(validationCallDescriptor),
-            type = validationCallDescriptor.returnType?.toIrType()!!
-        ).apply {
-
-            dispatchReceiver = receiver
-            // TODO(lmr): extensionReceiver.
-            // This might be something we want to be able to do in the cases where we want to
-            // build extension `changed(...)`  or `set(..) { ... }` methods
-
-            putTypeArguments(validationCall.typeArguments) { it.toIrType() }
-
-            putValueArgument(0, attributeValue)
-            val assignment = validation.assignment
-            if (assignment != null && validation.validationType != ValidationType.CHANGED) {
-                val assignmentLambdaDescriptor = validation.assignmentLambda
-                    ?: error("Expected assignmentLambda to be non-null")
-                val assignmentDescriptor = assignment.candidateDescriptor.original
-
-                val assignmentSymbol = when (assignmentDescriptor) {
-                    is PropertyDescriptor -> referenceFunction(
-                        assignmentDescriptor.setter!!
-                    )
-                    else -> referenceFunction(assignmentDescriptor)
-                }
-                val assignmentValueParameterDescriptor = assignmentLambdaDescriptor
-                    .valueParameters[0]
-
-                putValueArgument(
-                    1,
-                    irLambdaExpression(
-                        startOffset,
-                        endOffset,
-                        assignmentLambdaDescriptor,
-                        validationCallDescriptor.valueParameters[1].type.toIrType()
-                    ) { fn ->
-                        +irReturn(
-                            irCall(
-                                callee = assignmentSymbol,
-                                type = builtIns.unitType
-                            ).apply {
-                                putTypeArguments(assignment.typeArguments) { it.toIrType() }
-                                when (assignment.explicitReceiverKind) {
-                                    ExplicitReceiverKind.DISPATCH_RECEIVER -> {
-                                        dispatchReceiver = irGet(fn.extensionReceiverParameter!!)
-                                    }
-                                    ExplicitReceiverKind.EXTENSION_RECEIVER -> {
-                                        extensionReceiver = irGet(fn.extensionReceiverParameter!!)
-                                    }
-                                    ExplicitReceiverKind.BOTH_RECEIVERS -> {
-                                        // NOTE(lmr): This should not be possible. This would have
-                                        // to be an extension method on the ComposerUpdater class
-                                        // itself for the emittable type.
-                                        error(
-                                            "Extension instance methods are not allowed for " +
-                                                    "assignments"
-                                        )
-                                    }
-                                    ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> {
-                                        // NOTE(lmr): This is not possible
-                                        error("Static methods are invalid for assignments")
-                                    }
-                                }
-                                putValueArgument(
-                                    0,
-                                    irGet(
-                                        fn.getIrValueParameter(assignmentValueParameterDescriptor)
-                                    )
-                                )
-                            }
-                        )
-                    }
-                )
-            }
-        }
-    }
-}
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 b2b9ca7..ef37fa3 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
@@ -18,12 +18,9 @@
 
 import androidx.compose.plugins.kotlin.ComposeFqNames
 import androidx.compose.plugins.kotlin.KtxNameConventions
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
 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
+import androidx.compose.plugins.kotlin.composableTrackedContract
 import org.jetbrains.kotlin.backend.common.FileLoweringPass
 import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
 import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
@@ -270,6 +267,7 @@
 interface IrChangedBitMaskVariable : IrChangedBitMaskValue {
     fun asStatements(): List<IrStatement>
     fun irOrSetBitsAtSlot(slot: Int, value: IrExpression): IrExpression
+    fun irSetSlotUncertain(slot: Int): IrExpression
 }
 
 /**
@@ -600,9 +598,9 @@
         if (!scope.isComposable) return super.visitFunction(declaration)
         val restartable = declaration.shouldBeRestartable()
         val isLambda = declaration.isLambda()
-        // if the lambda is untracked, we generate the body like a non-restartable function since
-        // the group/update scope is not going to be handled by the RestartableFunction class
-        val isTracked = !declaration.descriptor.hasUntrackedAnnotation()
+
+        // we use != false because a null value is treated as "tracked"
+        val isTracked = declaration.descriptor.composableTrackedContract() != false
 
         if (declaration.body == null) return declaration
 
@@ -635,7 +633,7 @@
     // Currently, we make all composable functions restartable by default, unless:
     // 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)
+    // 3. They are a lambda (we use ComposableLambda<...> class for this instead)
     // 4. They are annotated as @ComposableContract(restartable = false)
     private fun IrFunction.shouldBeRestartable(): Boolean {
         // Only insert observe scopes in non-empty composable function
@@ -661,9 +659,6 @@
                     )
                 )
                     return false
-                if (it.isEmitInline(context.bindingContext)) {
-                    return false
-                }
             }
         }
 
@@ -771,7 +766,7 @@
         return declaration
     }
 
-    // Composable lambdas are always wrapped with a RestartableFunction class, which has its own
+    // Composable lambdas are always wrapped with a ComposableLambda class, which has its own
     // group in the invoke call. As a result, composable lambdas:
     // 1. receive no group at the root of their body
     // 2. cannot have default parameters, so have no default handling
@@ -782,7 +777,7 @@
         scope: Scope.FunctionScope,
         changedParam: IrChangedBitMaskValue
     ): IrStatement {
-        // no group, since restartableFunction should already create one
+        // no group, since composableLambda should already create one
         // no default logic
         val body = declaration.body!!
         val skipPreamble = mutableStatementContainer()
@@ -1147,6 +1142,7 @@
 
         // first we create the necessary local variables for default handling.
         val setDefaults = mutableStatementContainer()
+        val skipDefaults = mutableStatementContainer()
         parameters.forEachIndexed { index, param ->
             val defaultValue = param.defaultValue
             if (defaultParam != null && defaultValue != null) {
@@ -1191,12 +1187,42 @@
                         isVar = false,
                         exactName = true
                     ).also {
-                        setDefaults.statements.add(
-                            irIf(
-                                condition = irGetBit(defaultParam, index),
-                                body = irSet(it, transformedDefault)
+                        if (
+                            !defaultExprIsStatic[index] &&
+                            dirty is IrChangedBitMaskVariable
+                        ) {
+                            // if we are setting the parameter to the default expression and
+                            // running the default expression again, and the expression isn't
+                            // provably static, we can't be certain that the dirty value of
+                            // SAME is going to be valid. We must mark it as UNCERTAIN. In order
+                            // to avoid slot-table misalignment issues, we must mark it as
+                            // UNCERTAIN even when we skip the defaults, so that any child
+                            // function receives UNCERTAIN vs SAME/DIFFERENT deterministically.
+                            setDefaults.statements.add(
+                                irIf(
+                                    condition = irGetBit(defaultParam, index),
+                                    body = irBlock(
+                                        statements = listOf(
+                                            irSet(it, transformedDefault),
+                                            dirty.irSetSlotUncertain(index)
+                                        )
+                                    )
+                                )
                             )
-                        )
+                            skipDefaults.statements.add(
+                                irIf(
+                                    condition = irGetBit(defaultParam, index),
+                                    body = dirty.irSetSlotUncertain(index)
+                                )
+                            )
+                        } else {
+                            setDefaults.statements.add(
+                                irIf(
+                                    condition = irGetBit(defaultParam, index),
+                                    body = irSet(it, transformedDefault)
+                                )
+                            )
+                        }
                     }
                 }
 
@@ -1240,11 +1266,16 @@
                 }
 
                 val defaultValueIsStatic = defaultExprIsStatic[index]
+                val callChanged = irChanged(irGet(scope.remappedParams[param]!!))
+                val isChanged = if (defaultParam != null && !defaultValueIsStatic)
+                    irAndAnd(irIsProvided(defaultParam, index), callChanged)
+                else
+                    callChanged
                 val modifyDirtyFromChangedResult = dirty.irOrSetBitsAtSlot(
                     index,
                     irIfThenElse(
                         context.irBuiltIns.intType,
-                        irChanged(irGet(scope.remappedParams[param]!!)),
+                        isChanged,
                         // if the value has changed, update the bits in the slot to be
                         // "Different"
                         thenPart = irConst(ParamState.Different.bitsForSlot(index)),
@@ -1278,12 +1309,8 @@
                     // with an "Uncertain" state AND the value was provided. This is safe to do
                     // because this will remain true or false for *every* execution of the
                     // function, so we will never get a slot table misalignment as a result.
-                    val condition = if (defaultParam != null) irAndAnd(
-                        irIsProvided(defaultParam, index),
-                        irIsUncertain(changedParam, index)
-                    ) else irIsUncertain(changedParam, index)
                     irIf(
-                        condition = condition,
+                        condition = irIsUncertain(changedParam, index),
                         body = modifyDirtyFromChangedResult
                     )
                 }
@@ -1378,7 +1405,12 @@
                         )
                     ),
                     // composer.skipCurrentGroup()
-                    elsePart = irSkipCurrentGroup()
+                    elsePart = irBlock(
+                        statements = listOf(
+                            irSkipCurrentGroup(),
+                            *skipDefaults.statements.toTypedArray()
+                        )
+                    )
                 )
             )
         }
@@ -2242,13 +2274,6 @@
     }
 
     override fun visitCall(expression: IrCall): IrExpression {
-        val emitMetadata = context.irTrace[
-                ComposeWritableSlices.COMPOSABLE_EMIT_METADATA,
-                expression
-        ]
-        if (emitMetadata != null) {
-            return visitEmitCall(expression)
-        }
         if (expression.isTransformedComposableCall() || expression.isSyntheticComposableCall()) {
             return visitComposableCall(expression)
         }
@@ -2374,12 +2399,6 @@
         return expression
     }
 
-    private fun visitEmitCall(expression: IrCall): IrExpression {
-        encounteredComposableCall()
-        // TODO(lmr): eventually, we want to handle emits in this transform
-        return super.visitCall(expression)
-    }
-
     private fun visitKeyCall(expression: IrCall): IrExpression {
         val keyArgs = mutableListOf<IrExpression>()
         var blockArg: IrExpression? = null
@@ -2539,7 +2558,7 @@
                             return true
                         }
                     }
-                    if (symbol.descriptor.fqNameSafe == ComposeFqNames.restartableFunction) {
+                    if (symbol.descriptor.fqNameSafe == ComposeFqNames.composableLambda) {
                         // calls to this function are generated by the compiler, and this
                         // function behaves similar to a remember call in that the result will
                         // _always_ be the same and the resulting type is _always_ stable, so
@@ -3265,6 +3284,17 @@
                 )
             )
         }
+
+        override fun irSetSlotUncertain(slot: Int): IrExpression {
+            val temp = temps[paramIndexForSlot(slot)]
+            return irSet(
+                temp,
+                irAnd(
+                    irGet(temp),
+                    irInv(irConst(ParamState.Static.bitsForSlot(slot)))
+                )
+            )
+        }
     }
 }
 
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeResolutionMetadataTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeResolutionMetadataTransformer.kt
deleted file mode 100644
index a675c2a..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeResolutionMetadataTransformer.kt
+++ /dev/null
@@ -1,58 +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.compose.plugins.kotlin.compiler.lower
-
-import androidx.compose.plugins.kotlin.ComposableEmitDescriptor
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.irTrace
-import org.jetbrains.kotlin.backend.common.FileLoweringPass
-import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
-import org.jetbrains.kotlin.ir.declarations.IrFile
-import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
-import org.jetbrains.kotlin.ir.expressions.IrCall
-import org.jetbrains.kotlin.ir.expressions.IrExpression
-import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
-import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
-
-class ComposeResolutionMetadataTransformer(val context: IrPluginContext) :
-    IrElementTransformerVoid(),
-    FileLoweringPass,
-    ModuleLoweringPass {
-
-    override fun lower(module: IrModuleFragment) {
-        module.transformChildrenVoid(this)
-    }
-
-    override fun lower(irFile: IrFile) {
-        irFile.transformChildrenVoid(this)
-    }
-
-    override fun visitCall(expression: IrCall): IrExpression {
-
-        val descriptor = expression.symbol.descriptor
-
-        if (descriptor is ComposableEmitDescriptor) {
-            context.irTrace.record(
-                ComposeWritableSlices.COMPOSABLE_EMIT_METADATA,
-                expression,
-                descriptor
-            )
-        }
-
-        return super.visitCall(expression)
-    }
-}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt
index 848fa43..c09aea7 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt
@@ -19,9 +19,8 @@
 import androidx.compose.plugins.kotlin.ComposeUtils
 import androidx.compose.plugins.kotlin.ComposeUtils.composeInternalFqName
 import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.hasUntrackedAnnotation
+import androidx.compose.plugins.kotlin.composableTrackedContract
 import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
 import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
 import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
 import org.jetbrains.kotlin.backend.common.peek
@@ -133,10 +132,10 @@
     }
 }
 
-const val RESTARTABLE_FUNCTION = "restartableFunction"
-const val RESTARTABLE_FUNCTION_N = "restartableFunctionN"
-const val RESTARTABLE_FUNCTION_INSTANCE = "restartableFunctionInstance"
-const val RESTARTABLE_FUNCTION_N_INSTANCE = "restartableFunctionNInstance"
+const val COMPOSABLE_LAMBDA = "composableLambda"
+const val COMPOSABLE_LAMBDA_N = "composableLambdaN"
+const val COMPOSABLE_LAMBDA_INSTANCE = "composableLambdaInstance"
+const val COMPOSABLE_LAMBDA_N_INSTANCE = "composableLambdaNInstance"
 
 class ComposerLambdaMemoization(
     context: IrPluginContext,
@@ -340,15 +339,15 @@
     ): IrExpression {
         val function = expression.function
         val argumentCount = function.descriptor.valueParameters.size
-        val useRestartableFunctionN = argumentCount > MAX_RESTART_ARGUMENT_COUNT
+        val useComposableLambdaN = argumentCount > MAX_RESTART_ARGUMENT_COUNT
         val restartFunctionFactory =
             if (declarationContext.composable)
-                if (useRestartableFunctionN)
-                    RESTARTABLE_FUNCTION_N
-                else RESTARTABLE_FUNCTION
-            else if (useRestartableFunctionN)
-                RESTARTABLE_FUNCTION_N_INSTANCE
-                else RESTARTABLE_FUNCTION_INSTANCE
+                if (useComposableLambdaN)
+                    COMPOSABLE_LAMBDA_N
+                else COMPOSABLE_LAMBDA
+            else if (useComposableLambdaN)
+                COMPOSABLE_LAMBDA_N_INSTANCE
+                else COMPOSABLE_LAMBDA_INSTANCE
         val restartFactorySymbol =
             getTopLevelFunction(composeInternalFqName(restartFunctionFactory))
         val irBuilder = DeclarationIrBuilder(context,
@@ -379,8 +378,8 @@
             // tracked parameter
             putValueArgument(index++, irBuilder.irBoolean(expression.isTracked()))
 
-            // RestartableFunctionN requires the arity
-            if (useRestartableFunctionN) {
+            // ComposableLambdaN requires the arity
+            if (useComposableLambdaN) {
                 // arity parameter
                 putValueArgument(index++, irBuilder.irInt(argumentCount))
             }
@@ -501,16 +500,14 @@
                     )
                 )
                     return true
-                if (it.isEmitInline(context.bindingContext)) {
-                    return true
-                }
             }
         }
         return false
     }
 
     private fun IrExpression?.isNullOrStable() = this == null || type.toKotlinType().isStable()
-    private fun IrFunctionExpression.isTracked() = !function.descriptor.hasUntrackedAnnotation()
+    private fun IrFunctionExpression.isTracked() =
+        function.descriptor.composableTrackedContract() != false
 }
 
 // This must match the highest value of FunctionXX which is current Function22
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt
index 1f267cd..4d4e36f 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt
@@ -21,7 +21,6 @@
 import androidx.compose.plugins.kotlin.generateSymbols
 import androidx.compose.plugins.kotlin.hasComposableAnnotation
 import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
 import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
 import org.jetbrains.kotlin.backend.common.ir.copyTo
 import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
@@ -612,19 +611,7 @@
 
                 override fun visitCall(expression: IrCall): IrExpression {
                     val expr = if (!isNestedScope) {
-                        expression.withComposerParamIfNeeded(composerParam).also { call ->
-                            if (
-                                fn.isInline &&
-                                call !== expression &&
-                                call.isInlineParameterLambdaInvoke()
-                            ) {
-                                context.irTrace.record(
-                                    ComposeWritableSlices.IS_INLINE_COMPOSABLE_CALL,
-                                    call,
-                                    true
-                                )
-                            }
-                        }
+                        expression.withComposerParamIfNeeded(composerParam)
                     } else
                         expression
                     return super.visitCall(expr)
@@ -669,13 +656,6 @@
     }
 
     private fun IrFunction.isEmitInlineChildrenLambda(): Boolean {
-        descriptor.findPsi()?.let { psi ->
-            (psi as? KtFunctionLiteral)?.let {
-                if (it.isEmitInline(context.bindingContext)) {
-                    return true
-                }
-            }
-        }
         return false
     }
 }
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 f8248af..68abc3b 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
@@ -16,7 +16,6 @@
 
 package androidx.compose.plugins.kotlin.compiler.lower
 
-import androidx.compose.plugins.kotlin.ComposableEmitDescriptor
 import androidx.compose.plugins.kotlin.KtxNameConventions
 import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.descriptors.Visibilities
@@ -447,20 +446,15 @@
         forceParameterNames: Boolean = false,
         forceSingleLine: Boolean = false
     ) {
-        val descriptor = symbol.descriptor
         val arguments = mutableListOf<IrExpression>()
         val paramNames = mutableListOf<String>()
         var trailingLambda: IrExpression? = null
-        val isEmit = descriptor is ComposableEmitDescriptor
-        val isCompoundEmit = descriptor is ComposableEmitDescriptor && descriptor.hasChildren
-        val isLeafEmit = isEmit && !isCompoundEmit
-        var useParameterNames = forceParameterNames || isEmit
+        var useParameterNames = forceParameterNames
         for (i in 0 until valueArgumentsCount) {
             val arg = getValueArgument(i)
             if (arg != null) {
                 val param = symbol.owner.valueParameters[i]
                 val isTrailingLambda = i == symbol.owner.valueParameters.size - 1 &&
-                        !isLeafEmit &&
                         (
                             arg is IrFunctionExpression ||
                             (arg is IrBlock && arg.origin == IrStatementOrigin.LAMBDA)
diff --git a/compose/compose-dispatch/OWNERS b/compose/compose-dispatch/OWNERS
new file mode 100644
index 0000000..1cd0c38
--- /dev/null
+++ b/compose/compose-dispatch/OWNERS
@@ -0,0 +1,4 @@
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/compose/compose-dispatch/api/0.1.0-dev15.txt b/compose/compose-dispatch/api/0.1.0-dev15.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/0.1.0-dev15.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+    method public android.view.Choreographer getChoreographer();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+  }
+
+  public static final class AndroidUiDispatcher.Companion {
+    method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+    method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+    property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+    property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+  }
+
+  public final class AndroidUiDispatcherKt {
+  }
+
+  public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+    ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+    method public android.view.Choreographer getChoreographer();
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public interface MonotonicFrameClock {
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public final class MonotonicFrameClockKt {
+    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+}
+
diff --git a/compose/compose-dispatch/api/current.txt b/compose/compose-dispatch/api/current.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/current.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+    method public android.view.Choreographer getChoreographer();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+  }
+
+  public static final class AndroidUiDispatcher.Companion {
+    method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+    method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+    property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+    property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+  }
+
+  public final class AndroidUiDispatcherKt {
+  }
+
+  public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+    ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+    method public android.view.Choreographer getChoreographer();
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public interface MonotonicFrameClock {
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public final class MonotonicFrameClockKt {
+    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+}
+
diff --git a/compose/compose-dispatch/api/public_plus_experimental_0.1.0-dev15.txt b/compose/compose-dispatch/api/public_plus_experimental_0.1.0-dev15.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/public_plus_experimental_0.1.0-dev15.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+    method public android.view.Choreographer getChoreographer();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+  }
+
+  public static final class AndroidUiDispatcher.Companion {
+    method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+    method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+    property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+    property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+  }
+
+  public final class AndroidUiDispatcherKt {
+  }
+
+  public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+    ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+    method public android.view.Choreographer getChoreographer();
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public interface MonotonicFrameClock {
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public final class MonotonicFrameClockKt {
+    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+}
+
diff --git a/compose/compose-dispatch/api/public_plus_experimental_current.txt b/compose/compose-dispatch/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/public_plus_experimental_current.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+    method public android.view.Choreographer getChoreographer();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+  }
+
+  public static final class AndroidUiDispatcher.Companion {
+    method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+    method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+    property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+    property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+  }
+
+  public final class AndroidUiDispatcherKt {
+  }
+
+  public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+    ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+    method public android.view.Choreographer getChoreographer();
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public interface MonotonicFrameClock {
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public final class MonotonicFrameClockKt {
+    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+}
+
diff --git a/compose/compose-dispatch/api/res-0.1.0-dev15.txt b/compose/compose-dispatch/api/res-0.1.0-dev15.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/compose-dispatch/api/res-0.1.0-dev15.txt
diff --git a/compose/compose-dispatch/api/res-current.txt b/compose/compose-dispatch/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/compose-dispatch/api/res-current.txt
diff --git a/compose/compose-dispatch/api/restricted_0.1.0-dev15.txt b/compose/compose-dispatch/api/restricted_0.1.0-dev15.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/restricted_0.1.0-dev15.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+    method public android.view.Choreographer getChoreographer();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+  }
+
+  public static final class AndroidUiDispatcher.Companion {
+    method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+    method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+    property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+    property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+  }
+
+  public final class AndroidUiDispatcherKt {
+  }
+
+  public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+    ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+    method public android.view.Choreographer getChoreographer();
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public interface MonotonicFrameClock {
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public final class MonotonicFrameClockKt {
+    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+}
+
diff --git a/compose/compose-dispatch/api/restricted_current.txt b/compose/compose-dispatch/api/restricted_current.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/restricted_current.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+    method public android.view.Choreographer getChoreographer();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+  }
+
+  public static final class AndroidUiDispatcher.Companion {
+    method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+    method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+    property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+    property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+  }
+
+  public final class AndroidUiDispatcherKt {
+  }
+
+  public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+    ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+    method public android.view.Choreographer getChoreographer();
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public interface MonotonicFrameClock {
+    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+  public final class MonotonicFrameClockKt {
+    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+  }
+
+}
+
diff --git a/compose/compose-dispatch/build.gradle b/compose/compose-dispatch/build.gradle
new file mode 100644
index 0000000..bf2cb7c
--- /dev/null
+++ b/compose/compose-dispatch/build.gradle
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+    id("AndroidXPlugin")
+    id("AndroidXUiPlugin")
+    id("com.android.library")
+    id("kotlin-multiplatform")
+}
+
+kotlin {
+    android()
+    jvm("desktop")
+
+    sourceSets {
+        commonMain.dependencies {
+            implementation(KOTLIN_STDLIB_COMMON)
+            api(KOTLIN_COROUTINES_CORE_COMMON)
+        }
+        jvmMain.dependencies {
+            implementation(KOTLIN_STDLIB)
+            api(KOTLIN_COROUTINES_CORE)
+        }
+        androidMain {
+            dependencies {
+                api "androidx.annotation:annotation:1.1.0"
+                implementation("androidx.core:core-ktx:1.1.0")
+                implementation(KOTLIN_COROUTINES_ANDROID)
+            }
+            dependsOn jvmMain
+        }
+
+        androidTest.dependencies {
+            implementation(ANDROIDX_TEST_RULES)
+            implementation(ANDROIDX_TEST_RUNNER)
+            implementation(JUNIT)
+        }
+
+        androidAndroidTest.dependencies {
+            implementation(ANDROIDX_TEST_RULES)
+            implementation(ANDROIDX_TEST_RUNNER)
+            implementation(ANDROIDX_TEST_EXT_KTX)
+            implementation(ANDROIDX_TEST_UIAUTOMATOR)
+            implementation(JUNIT)
+        }
+
+        desktopMain {
+            dependsOn jvmMain
+        }
+    }
+}
+
+android {
+    buildTypes {
+        debug {
+            testCoverageEnabled = false
+        }
+        release {
+            testCoverageEnabled = false
+        }
+    }
+}
+
+androidx {
+    name = "Compose Dispatch"
+    publish = Publish.SNAPSHOT_AND_RELEASE
+    mavenVersion = LibraryVersions.COMPOSE
+    mavenGroup = LibraryGroups.COMPOSE
+    inceptionYear = "2020"
+    description = "Platform timing and event dispatch utilities"
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions {
+        freeCompilerArgs += [
+            "-Xuse-experimental=kotlin.Experimental"
+        ]
+        useIR = true
+    }
+}
diff --git a/compose/compose-dispatch/src/androidAndroidTest/AndroidManifest.xml b/compose/compose-dispatch/src/androidAndroidTest/AndroidManifest.xml
new file mode 100644
index 0000000..a6c2833
--- /dev/null
+++ b/compose/compose-dispatch/src/androidAndroidTest/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.compose.dispatch.test">
+    <application>
+        <activity android:name="androidx.compose.dispatch.TestActivity" />
+    </application>
+</manifest>
diff --git a/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/AndroidUiDispatcherTest.kt b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/AndroidUiDispatcherTest.kt
new file mode 100644
index 0000000..c031c35
--- /dev/null
+++ b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/AndroidUiDispatcherTest.kt
@@ -0,0 +1,159 @@
+/*
+ * 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.dispatch
+
+import android.graphics.Rect
+import android.view.Choreographer
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup.LayoutParams
+import androidx.core.view.doOnLayout
+import androidx.test.ext.junit.rules.activityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class AndroidUiDispatcherTest {
+    @get:Rule
+    val rule = activityScenarioRule<TestActivity>()
+
+    @Test
+    fun currentThreadIsMainOnMainThread() = runBlocking(Dispatchers.Main) {
+        assertSame(AndroidUiDispatcher.Main, AndroidUiDispatcher.CurrentThread)
+    }
+
+    @Test
+    fun runsBeforeFrameCallback() = runBlocking(Dispatchers.Main) {
+        rule.scenario.onActivity {
+            // Force creation of decor view to ensure we have a frame scheduled
+            it.window.decorView
+        }
+
+        var ranOnUiDispatcher = false
+        launch(AndroidUiDispatcher.Main) { ranOnUiDispatcher = true }
+
+        val choreographerResult = CompletableDeferred<Boolean>()
+        Choreographer.getInstance().postFrameCallback {
+            choreographerResult.complete(ranOnUiDispatcher)
+        }
+
+        assertTrue("UI dispatcher ran before choreographer frame", choreographerResult.await())
+    }
+
+    /**
+     * Verify that [AndroidUiDispatcher] will run a resumed continuation before
+     * the next frame is drawn, even if that continuation is resumed during the dispatch of
+     * batched input. Batched input is dispatched during an atomic sequence of events handled
+     * by the [Choreographer] of input => animation callbacks => measure => layout => draw,
+     * which will cause dispatchers that schedule entirely based on [android.os.Handler] messages
+     * to miss the current frame.
+     *
+     * This test also verifies that a call to [AndroidUiDispatcher.frameClock]'s
+     * [MonotonicFrameClock.withFrameNanos] will resume in time to make the current frame if called
+     * from the situation described above, and that subsequent calls will wait until the next frame.
+     */
+    @Test
+    fun runsBeforeFrameDispatchedByInput() = runBlocking {
+        val ranInputJobOnFrame = CompletableDeferred<Int>()
+        val viewTouchedOnFrame = CompletableDeferred<Int>()
+        val withFrameOnFrame = CompletableDeferred<Int>()
+        val withFrameSecondCall = CompletableDeferred<Int>()
+        val layoutRect = CompletableDeferred<Rect>()
+        var preDrawCount = 0
+        rule.scenario.onActivity { activity ->
+            activity.setContentView(
+                View(activity).apply {
+                    setOnTouchListener { _, motionEvent ->
+                        if (motionEvent.action != MotionEvent.ACTION_UP) {
+                            return@setOnTouchListener true
+                        }
+                        viewTouchedOnFrame.complete(preDrawCount)
+                        launch(AndroidUiDispatcher.Main) {
+                            ranInputJobOnFrame.complete(preDrawCount)
+                            AndroidUiDispatcher.Main.frameClock.withFrameNanos {
+                                withFrameOnFrame.complete(preDrawCount)
+                            }
+                            AndroidUiDispatcher.Main.frameClock.withFrameNanos {
+                                withFrameSecondCall.complete(preDrawCount)
+                            }
+                        }
+                        invalidate()
+                        true
+                    }
+                    viewTreeObserver.addOnPreDrawListener {
+                        preDrawCount++
+                        true
+                    }
+                    doOnLayout { view ->
+                        val rect = Rect()
+                        view.getGlobalVisibleRect(rect)
+                        layoutRect.complete(rect)
+                    }
+                },
+                LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
+            )
+        }
+
+        with(UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())) {
+            // Use a swipe event with many steps to force the input dispatcher into batched mode.
+            // A simple click here will not force batched mode of input dispatch to the view
+            // hierarchy and the test will pass using a solely Handler-based dispatcher.
+            // Batched mode will wait to dispatch events until the frame begins, causing
+            // a Handler message to miss the frame, but AndroidUiDispatchers.Main should resume
+            // in the same frame if the resume was triggered by the input event.
+            val rect = layoutRect.await()
+            swipe(rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1, 30)
+        }
+
+        withTimeout(3_000) {
+            val viewTouched = viewTouchedOnFrame.await()
+            val inputJob = ranInputJobOnFrame.await()
+            assertNotEquals(0, viewTouched)
+            assertNotEquals(0, inputJob)
+            assertEquals(
+                "touch and launched job resume happened on same frame",
+                viewTouched,
+                inputJob
+            )
+            assertEquals(
+                "withFrame ran on the same frame where it was called",
+                inputJob,
+                withFrameOnFrame.await()
+            )
+            assertEquals(
+                "second withFrame call was invoked on the very next frame",
+                inputJob + 1,
+                withFrameSecondCall.await()
+            )
+        }
+    }
+}
diff --git a/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/TestActivity.kt b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/TestActivity.kt
new file mode 100644
index 0000000..4afcf14
--- /dev/null
+++ b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/TestActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.dispatch
+
+import androidx.core.app.ComponentActivity
+
+class TestActivity : ComponentActivity()
\ No newline at end of file
diff --git a/compose/compose-dispatch/src/androidMain/AndroidManifest.xml b/compose/compose-dispatch/src/androidMain/AndroidManifest.xml
new file mode 100644
index 0000000..c63b040
--- /dev/null
+++ b/compose/compose-dispatch/src/androidMain/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest package="androidx.compose.dispatch"/>
diff --git a/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiDispatcher.kt b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiDispatcher.kt
new file mode 100644
index 0000000..e3d3a05
--- /dev/null
+++ b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiDispatcher.kt
@@ -0,0 +1,184 @@
+/*
+ * 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.dispatch
+
+import android.os.Looper
+import android.view.Choreographer
+import androidx.core.os.HandlerCompat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlin.coroutines.CoroutineContext
+
+/**
+ * A [CoroutineDispatcher] that will perform dispatch during a [handler] callback or
+ * [choreographer]'s animation frame stage, whichever comes first. Use [Main] to obtain
+ * a dispatcher for the process's main thread (i.e. the activity thread) or [CurrentThread]
+ * to obtain a dispatcher for the current thread.
+ */
+// Implementation note: the constructor is private to direct users toward the companion object
+// accessors for the main/current threads. A choreographer must be obtained from its current
+// thread as per the only public API surface for obtaining one as of this writing, and the
+// choreographer and handler must match. Constructing an AndroidUiDispatcher with a handler
+// not marked as async will adversely affect dispatch behavior but not to the point of
+// incorrectness; more operations would be deferred to the choreographer frame as racing handler
+// messages would wait behind a frame barrier.
+@OptIn(ExperimentalStdlibApi::class)
+class AndroidUiDispatcher private constructor(
+    val choreographer: Choreographer,
+    private val handler: android.os.Handler
+) : CoroutineDispatcher() {
+
+    // Guards all properties in this class
+    private val lock = Any()
+
+    private val toRunTrampolined = ArrayDeque<Runnable>()
+    private var toRunOnFrame = mutableListOf<Choreographer.FrameCallback>()
+    private var spareToRunOnFrame = mutableListOf<Choreographer.FrameCallback>()
+    private var scheduledTrampolineDispatch = false
+    private var scheduledFrameDispatch = false
+
+    private val dispatchCallback = object : Choreographer.FrameCallback, Runnable {
+        override fun run() {
+            performTrampolineDispatch()
+            synchronized(lock) {
+                if (toRunOnFrame.isEmpty()) {
+                    choreographer.removeFrameCallback(this)
+                    scheduledFrameDispatch = false
+                }
+            }
+        }
+
+        override fun doFrame(frameTimeNanos: Long) {
+            handler.removeCallbacks(this)
+            performTrampolineDispatch()
+            performFrameDispatch(frameTimeNanos)
+        }
+    }
+
+    private fun nextTask(): Runnable? = synchronized(lock) {
+        toRunTrampolined.removeFirstOrNull()
+    }
+
+    private fun performTrampolineDispatch() {
+        do {
+            var task = nextTask()
+            while (task != null) {
+                task.run()
+                task = nextTask()
+            }
+        } while (
+        // We don't dispatch holding the lock so that other tasks can get in on our
+        // trampolining time slice, but once we're done, make sure nothing added a new task
+        // before we set scheduledDispatch = false, which would prevent the next dispatch
+        // from being correctly scheduled. Loop to run these stragglers now.
+            synchronized(lock) {
+                if (toRunTrampolined.isEmpty()) {
+                    scheduledTrampolineDispatch = false
+                    false
+                } else true
+            }
+        )
+    }
+
+    private fun performFrameDispatch(frameTimeNanos: Long) {
+        val toRun = synchronized(lock) {
+            if (!scheduledFrameDispatch) return
+            scheduledFrameDispatch = false
+            val result = toRunOnFrame
+            toRunOnFrame = spareToRunOnFrame
+            spareToRunOnFrame = result
+            result
+        }
+        for (i in 0 until toRun.size) {
+            // This callback can't throw, see AndroidUiCompositionFrameClock
+            toRun[i].doFrame(frameTimeNanos)
+        }
+        toRun.clear()
+    }
+
+    internal fun postFrameCallback(callback: Choreographer.FrameCallback) {
+        synchronized(lock) {
+            toRunOnFrame.add(callback)
+            if (!scheduledFrameDispatch) {
+                scheduledFrameDispatch = true
+                choreographer.postFrameCallback(dispatchCallback)
+            }
+        }
+    }
+
+    internal fun removeFrameCallback(callback: Choreographer.FrameCallback) {
+        synchronized(lock) {
+            toRunOnFrame.remove(callback)
+        }
+    }
+
+    /**
+     * A [MonotonicFrameClock] associated with this [AndroidUiDispatcher]'s [choreographer]
+     * that may be used to await [Choreographer] frame dispatch.
+     */
+    val frameClock: MonotonicFrameClock = AndroidUiFrameClock(choreographer)
+
+    override fun dispatch(context: CoroutineContext, block: Runnable) {
+        synchronized(lock) {
+            toRunTrampolined.addLast(block)
+            if (!scheduledTrampolineDispatch) {
+                scheduledTrampolineDispatch = true
+                handler.post(dispatchCallback)
+                if (!scheduledFrameDispatch) {
+                    scheduledFrameDispatch = true
+                    choreographer.postFrameCallback(dispatchCallback)
+                }
+            }
+        }
+    }
+
+    companion object {
+        /**
+         * The [AndroidUiDispatcher] for the process's main thread.
+         */
+        val Main by lazy {
+            AndroidUiDispatcher(
+                if (isMainThread()) Choreographer.getInstance()
+                else runBlocking(Dispatchers.Main) { Choreographer.getInstance() },
+                HandlerCompat.createAsync(Looper.getMainLooper())
+            )
+        }
+
+        private val currentThread: ThreadLocal<AndroidUiDispatcher> =
+            object : ThreadLocal<AndroidUiDispatcher>() {
+                override fun initialValue(): AndroidUiDispatcher = AndroidUiDispatcher(
+                    Choreographer.getInstance(),
+                    HandlerCompat.createAsync(Looper.myLooper()
+                        ?: error("no Looper on this thread"))
+                )
+            }
+
+        /**
+         * The canonical [AndroidUiDispatcher] for the calling thread. Returns [Main] if accessed
+         * from the process's main thread.
+         *
+         * Throws [IllegalArgumentException] if the calling thread does not have
+         * both a [Choreographer] and an active [Looper].
+         */
+        val CurrentThread: AndroidUiDispatcher get() = if (isMainThread()) Main else {
+            currentThread.get() ?: error("no AndroidUiDispatcher for this thread")
+        }
+    }
+}
+
+private fun isMainThread() = Looper.myLooper() === Looper.getMainLooper()
diff --git a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiCompositionFrameClock.kt b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiFrameClock.kt
similarity index 88%
rename from compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiCompositionFrameClock.kt
rename to compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiFrameClock.kt
index 8651c94..5f04241 100644
--- a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiCompositionFrameClock.kt
+++ b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiFrameClock.kt
@@ -14,27 +14,23 @@
  * limitations under the License.
  */
 
-package androidx.compose
+package androidx.compose.dispatch
 
 import android.view.Choreographer
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlin.coroutines.ContinuationInterceptor
 import kotlin.coroutines.coroutineContext
 
-/**
- * A [CompositionFrameClock] driven by an [android.view.Choreographer].
- */
-class AndroidUiCompositionFrameClock(
+class AndroidUiFrameClock(
     val choreographer: Choreographer
-) : CompositionFrameClock {
-
+) : MonotonicFrameClock {
     override suspend fun <R> withFrameNanos(
         onFrame: (Long) -> R
     ): R {
         val uiDispatcher = coroutineContext[ContinuationInterceptor] as? AndroidUiDispatcher
         return suspendCancellableCoroutine { co ->
             // Important: this callback won't throw, and AndroidUiDispatcher counts on it.
-            val callback = ChoreographerFrameCallback { frameTimeNanos ->
+            val callback = Choreographer.FrameCallback { frameTimeNanos ->
                 co.resumeWith(runCatching { onFrame(frameTimeNanos) })
             }
 
@@ -54,4 +50,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/compose/compose-dispatch/src/commonMain/kotlin/androidx/compose/dispatch/MonotonicFrameClock.kt b/compose/compose-dispatch/src/commonMain/kotlin/androidx/compose/dispatch/MonotonicFrameClock.kt
new file mode 100644
index 0000000..2561001
--- /dev/null
+++ b/compose/compose-dispatch/src/commonMain/kotlin/androidx/compose/dispatch/MonotonicFrameClock.kt
@@ -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.compose.dispatch
+
+/**
+ * Provides a time source for display frames and the ability to perform an action on the next frame.
+ * This may be used for matching timing with the refresh rate of a display or otherwise
+ * synchronizing work with a desired frame rate.
+ */
+interface MonotonicFrameClock {
+    /**
+     * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
+     * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
+     * [onFrame].
+     *
+     * `frameTimeNanos` should be used when calculating animation time deltas from frame to frame
+     * as it may be normalized to the target time for the frame, not necessarily a direct,
+     * "now" value.
+     *
+     * The time base of the value provided by [withFrameNanos] is implementation defined.
+     * Time values provided are monotonically increasing; after a call to [withFrameNanos]
+     * completes it must not provide the same value again for a subsequent call.
+     */
+    suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R
+}
+
+/**
+ * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
+ * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
+ * [onFrame].
+ *
+ * `frameTimeNanos` should be used when calculating animation time deltas from frame to frame
+ * as it may be normalized to the target time for the frame, not necessarily a direct,
+ * "now" value.
+ *
+ * The time base of the value provided by [MonotonicFrameClock.withFrameMillis] is
+ * implementation defined. Time values provided are monotonically increasing; after a call to
+ * [MonotonicFrameClock.withFrameMillis] completes it must not provide the same value again for
+ * a subsequent call.
+ */
+@Suppress("UnnecessaryLambdaCreation")
+suspend inline fun <R> MonotonicFrameClock.withFrameMillis(
+    crossinline onFrame: (frameTimeMillis: Long) -> R
+): R = withFrameNanos { onFrame(it / 1_000_000L) }
diff --git a/compose/compose-runtime/api/0.1.0-dev15.txt b/compose/compose-runtime/api/0.1.0-dev15.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/0.1.0-dev15.txt
+++ b/compose/compose-runtime/api/0.1.0-dev15.txt
@@ -1,13 +1,26 @@
 // Signature format: 3.0
 package androidx.compose {
 
+  @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+    ctor public AbstractApplier(T! root);
+    method public void down(T? node);
+    method public T! getCurrent();
+    method public final T! getRoot();
+    method protected final void move(java.util.List<T>, int from, int to, int count);
+    method protected final void remove(java.util.List<T>, int index, int count);
+    method public void reset();
+    method public void setCurrent(T! p);
+    method public void up();
+    property public T! current;
+  }
+
   public final class ActualAndroidKt {
   }
 
   public final class ActualJvmKt {
   }
 
-  @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+  @androidx.compose.Stable public abstract sealed class Ambient<T> {
     method public final inline T! getCurrent();
     property public final inline T! current;
   }
@@ -25,29 +38,7 @@
     property public final boolean valid;
   }
 
-  public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
-    ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
-    method public android.view.Choreographer getChoreographer();
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-  }
-
-  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
-    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
-    method public android.view.Choreographer getChoreographer();
-    method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
-    property public final androidx.compose.CompositionFrameClock compositionFrameClock;
-    field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
-  }
-
-  public static final class AndroidUiDispatcher.Companion {
-    method public androidx.compose.AndroidUiDispatcher getCurrentThread();
-    method public androidx.compose.AndroidUiDispatcher getMain();
-    property public final androidx.compose.AndroidUiDispatcher CurrentThread;
-    property public final androidx.compose.AndroidUiDispatcher Main;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
-    ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+  @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
     method public void down(N? node);
     method public N! getCurrent();
     method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
     method public void remove(int index, int count);
     method public void reset();
     method public void up();
-    property public final N! current;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
-    method public void end(N?, N? instance, N? parent);
-    method public void insertAt(N?, int index, N? instance);
-    method public void move(N?, int from, int to, int count);
-    method public void removeAt(N?, int index, int count);
-    method public void start(N?, N? instance);
+    property public abstract N! current;
   }
 
   public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
     method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
   }
 
-  @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.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;
+    method public abstract boolean tracked() default true;
   }
 
   @kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> {
+  public final class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
-    method @androidx.compose.InternalComposeApi public final void applyChanges();
-    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 @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
-    method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
-    method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
-    method @androidx.compose.ComposeCompilerApi public final void endDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
-    method @androidx.compose.ComposeCompilerApi public final void endNode();
-    method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
-    method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
-    method public final int getCurrentCompoundKeyHash();
-    method public final boolean getDefaultsInvalid();
-    method public final boolean getInserting();
-    method public final androidx.compose.Recomposer getRecomposer();
-    method public final boolean getSkipping();
-    method public final androidx.compose.SlotTable getSlotTable();
-    method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
-    method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
-    method @androidx.compose.InternalComposeApi public final boolean recompose();
-    method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
-    method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
-    method @androidx.compose.ComposeCompilerApi public final void startDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
-    method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final N! useNode();
+    method @androidx.compose.InternalComposeApi public void applyChanges();
+    method @Deprecated public 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 @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+    method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+    method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+    method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+    method @androidx.compose.ComposeCompilerApi public void endDefaults();
+    method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+    method @androidx.compose.ComposeCompilerApi public void endNode();
+    method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+    method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+    method public androidx.compose.Applier<N> getApplier();
+    method public int getCurrentCompoundKeyHash();
+    method public boolean getDefaultsInvalid();
+    method public boolean getInserting();
+    method public androidx.compose.Recomposer getRecomposer();
+    method public boolean getSkipping();
+    method public androidx.compose.SlotTable getSlotTable();
+    method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+    method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+    method @androidx.compose.InternalComposeApi public boolean recompose();
+    method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+    method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+    method @androidx.compose.ComposeCompilerApi public void startDefaults();
+    method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+    method @androidx.compose.ComposeCompilerApi public void startNode();
+    method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public N! useNode();
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean inserting;
@@ -151,20 +135,11 @@
   }
 
   public final class ComposerKt {
-    method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static androidx.compose.Composer<?> getComposer();
     method public static androidx.compose.Composer<?> getCurrentComposer();
   }
 
-  public final class ComposerUpdater<N, T extends N> {
-    ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
-    method public androidx.compose.Composer<N> getComposer();
-    method public T! getNode();
-    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-  }
-
   @Deprecated public interface ComposerValidator {
     method @Deprecated public boolean changed(int value);
     method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+  public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
     ctor public CompositionCoroutineScope();
     method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
   }
 
-  public interface CompositionFrameClock {
+  @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
     method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionFrameClockKt {
     method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
     method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
     method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
-    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+    method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionKt {
-    method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
     method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
   }
 
   public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
     method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
   }
 
+  public final class EmitKt {
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+  }
+
   public final class ExpectKt {
   }
 
@@ -241,7 +221,7 @@
     method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
     method public void nextFrame();
     method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
-    field public static final androidx.compose.FrameManager! INSTANCE;
+    field public static final androidx.compose.FrameManager INSTANCE;
   }
 
   @androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
     method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
   }
 
-  public final class NullCompilationScope {
-    method public kotlin.Unit getComposer();
+  @Deprecated public final class NullCompilationScope {
+    method @Deprecated public kotlin.Unit getComposer();
     property public final kotlin.Unit composer;
-    field public static final androidx.compose.NullCompilationScope! INSTANCE;
+    field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
   }
 
   public final class ObserveKt {
@@ -316,7 +296,7 @@
     method public void removeValue(V value);
   }
 
-  @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+  @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
     method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
   }
 
@@ -332,12 +312,12 @@
   public final class Recomposer {
     ctor public Recomposer();
     method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public androidx.compose.CompositionFrameClock getFrameClock();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
     method public boolean hasPendingChanges();
-    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
-    property public final androidx.compose.CompositionFrameClock frameClock;
-    field public static final androidx.compose.Recomposer.Companion! Companion;
+    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.Recomposer.Companion Companion;
   }
 
   public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
   }
 
   public final class RecomposerKt {
-    method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
   }
 
   public final class RememberKt {
@@ -430,7 +410,7 @@
     method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
     method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
     property public final int size;
-    field public static final androidx.compose.SlotTable.Companion! Companion;
+    field public static final androidx.compose.SlotTable.Companion Companion;
   }
 
   @androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
     method public abstract Class<?>[] types();
   }
 
-  @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  }
+
+  public final class Updater<T> {
+    ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+    method public androidx.compose.Composer<?> getComposer();
+    method public T! getNode();
+    method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
   }
 
 }
@@ -661,8 +652,8 @@
 
 package androidx.compose.internal {
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
-    ctor public RestartableFunction(int key, boolean tracked);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+    ctor public ComposableLambda(int key, boolean tracked);
     method public int getKey();
     method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
     method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+  public final class ComposableLambdaKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
-    ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+    ctor public ComposableLambdaN(int key, boolean tracked, int arity);
     method public int getArity();
     method public int getKey();
     method public R! invoke(java.lang.Object?... args);
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionNKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+  public final class ComposableLambdaNKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
 }
diff --git a/compose/compose-runtime/api/api_lint.ignore b/compose/compose-runtime/api/api_lint.ignore
index 215da53..bd61dc8 100644
--- a/compose/compose-runtime/api/api_lint.ignore
+++ b/compose/compose-runtime/api/api_lint.ignore
@@ -41,10 +41,6 @@
     Exceptions must be named `FooException`, was `FrameAborted`
 
 
-KotlinOperator: androidx.compose.ComposerUpdater#set(V, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit>):
-    Note that adding the `operator` keyword would allow calling this method using operator syntax
-KotlinOperator: androidx.compose.ComposerUpdater#set(int, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit>):
-    Note that adding the `operator` keyword would allow calling this method using operator syntax
 KotlinOperator: androidx.compose.SlotReader#get(androidx.compose.Anchor):
     Note that adding the `operator` keyword would allow calling this method using operator syntax
 KotlinOperator: androidx.compose.SlotReader#get(int):
@@ -53,6 +49,10 @@
     Note that adding the `operator` keyword would allow calling this method using operator syntax
 KotlinOperator: androidx.compose.SlotWriter#get(int):
     Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.compose.Updater#set(V, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit>):
+    Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.compose.Updater#set(int, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit>):
+    Note that adding the `operator` keyword would allow calling this method using operator syntax
 
 
 MissingNullability: androidx.compose.BuildableMap#containsKey(Object) parameter #0:
@@ -76,6 +76,7 @@
 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)
 
+
 NotCloseable: androidx.compose.SlotReader:
     Classes that release resources (close()) should implement AutoClosable and CloseGuard: class androidx.compose.SlotReader
 NotCloseable: androidx.compose.SlotWriter:
diff --git a/compose/compose-runtime/api/current.txt b/compose/compose-runtime/api/current.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/current.txt
+++ b/compose/compose-runtime/api/current.txt
@@ -1,13 +1,26 @@
 // Signature format: 3.0
 package androidx.compose {
 
+  @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+    ctor public AbstractApplier(T! root);
+    method public void down(T? node);
+    method public T! getCurrent();
+    method public final T! getRoot();
+    method protected final void move(java.util.List<T>, int from, int to, int count);
+    method protected final void remove(java.util.List<T>, int index, int count);
+    method public void reset();
+    method public void setCurrent(T! p);
+    method public void up();
+    property public T! current;
+  }
+
   public final class ActualAndroidKt {
   }
 
   public final class ActualJvmKt {
   }
 
-  @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+  @androidx.compose.Stable public abstract sealed class Ambient<T> {
     method public final inline T! getCurrent();
     property public final inline T! current;
   }
@@ -25,29 +38,7 @@
     property public final boolean valid;
   }
 
-  public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
-    ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
-    method public android.view.Choreographer getChoreographer();
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-  }
-
-  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
-    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
-    method public android.view.Choreographer getChoreographer();
-    method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
-    property public final androidx.compose.CompositionFrameClock compositionFrameClock;
-    field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
-  }
-
-  public static final class AndroidUiDispatcher.Companion {
-    method public androidx.compose.AndroidUiDispatcher getCurrentThread();
-    method public androidx.compose.AndroidUiDispatcher getMain();
-    property public final androidx.compose.AndroidUiDispatcher CurrentThread;
-    property public final androidx.compose.AndroidUiDispatcher Main;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
-    ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+  @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
     method public void down(N? node);
     method public N! getCurrent();
     method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
     method public void remove(int index, int count);
     method public void reset();
     method public void up();
-    property public final N! current;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
-    method public void end(N?, N? instance, N? parent);
-    method public void insertAt(N?, int index, N? instance);
-    method public void move(N?, int from, int to, int count);
-    method public void removeAt(N?, int index, int count);
-    method public void start(N?, N? instance);
+    property public abstract N! current;
   }
 
   public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
     method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
   }
 
-  @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.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;
+    method public abstract boolean tracked() default true;
   }
 
   @kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> {
+  public final class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
-    method @androidx.compose.InternalComposeApi public final void applyChanges();
-    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 @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
-    method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
-    method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
-    method @androidx.compose.ComposeCompilerApi public final void endDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
-    method @androidx.compose.ComposeCompilerApi public final void endNode();
-    method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
-    method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
-    method public final int getCurrentCompoundKeyHash();
-    method public final boolean getDefaultsInvalid();
-    method public final boolean getInserting();
-    method public final androidx.compose.Recomposer getRecomposer();
-    method public final boolean getSkipping();
-    method public final androidx.compose.SlotTable getSlotTable();
-    method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
-    method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
-    method @androidx.compose.InternalComposeApi public final boolean recompose();
-    method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
-    method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
-    method @androidx.compose.ComposeCompilerApi public final void startDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
-    method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final N! useNode();
+    method @androidx.compose.InternalComposeApi public void applyChanges();
+    method @Deprecated public 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 @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+    method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+    method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+    method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+    method @androidx.compose.ComposeCompilerApi public void endDefaults();
+    method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+    method @androidx.compose.ComposeCompilerApi public void endNode();
+    method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+    method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+    method public androidx.compose.Applier<N> getApplier();
+    method public int getCurrentCompoundKeyHash();
+    method public boolean getDefaultsInvalid();
+    method public boolean getInserting();
+    method public androidx.compose.Recomposer getRecomposer();
+    method public boolean getSkipping();
+    method public androidx.compose.SlotTable getSlotTable();
+    method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+    method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+    method @androidx.compose.InternalComposeApi public boolean recompose();
+    method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+    method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+    method @androidx.compose.ComposeCompilerApi public void startDefaults();
+    method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+    method @androidx.compose.ComposeCompilerApi public void startNode();
+    method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public N! useNode();
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean inserting;
@@ -151,20 +135,11 @@
   }
 
   public final class ComposerKt {
-    method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static androidx.compose.Composer<?> getComposer();
     method public static androidx.compose.Composer<?> getCurrentComposer();
   }
 
-  public final class ComposerUpdater<N, T extends N> {
-    ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
-    method public androidx.compose.Composer<N> getComposer();
-    method public T! getNode();
-    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-  }
-
   @Deprecated public interface ComposerValidator {
     method @Deprecated public boolean changed(int value);
     method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+  public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
     ctor public CompositionCoroutineScope();
     method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
   }
 
-  public interface CompositionFrameClock {
+  @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
     method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionFrameClockKt {
     method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
     method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
     method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
-    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+    method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionKt {
-    method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
     method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
   }
 
   public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
     method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
   }
 
+  public final class EmitKt {
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+  }
+
   public final class ExpectKt {
   }
 
@@ -241,7 +221,7 @@
     method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
     method public void nextFrame();
     method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
-    field public static final androidx.compose.FrameManager! INSTANCE;
+    field public static final androidx.compose.FrameManager INSTANCE;
   }
 
   @androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
     method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
   }
 
-  public final class NullCompilationScope {
-    method public kotlin.Unit getComposer();
+  @Deprecated public final class NullCompilationScope {
+    method @Deprecated public kotlin.Unit getComposer();
     property public final kotlin.Unit composer;
-    field public static final androidx.compose.NullCompilationScope! INSTANCE;
+    field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
   }
 
   public final class ObserveKt {
@@ -316,7 +296,7 @@
     method public void removeValue(V value);
   }
 
-  @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+  @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
     method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
   }
 
@@ -332,12 +312,12 @@
   public final class Recomposer {
     ctor public Recomposer();
     method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public androidx.compose.CompositionFrameClock getFrameClock();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
     method public boolean hasPendingChanges();
-    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
-    property public final androidx.compose.CompositionFrameClock frameClock;
-    field public static final androidx.compose.Recomposer.Companion! Companion;
+    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.Recomposer.Companion Companion;
   }
 
   public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
   }
 
   public final class RecomposerKt {
-    method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
   }
 
   public final class RememberKt {
@@ -430,7 +410,7 @@
     method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
     method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
     property public final int size;
-    field public static final androidx.compose.SlotTable.Companion! Companion;
+    field public static final androidx.compose.SlotTable.Companion Companion;
   }
 
   @androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
     method public abstract Class<?>[] types();
   }
 
-  @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  }
+
+  public final class Updater<T> {
+    ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+    method public androidx.compose.Composer<?> getComposer();
+    method public T! getNode();
+    method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
   }
 
 }
@@ -661,8 +652,8 @@
 
 package androidx.compose.internal {
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
-    ctor public RestartableFunction(int key, boolean tracked);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+    ctor public ComposableLambda(int key, boolean tracked);
     method public int getKey();
     method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
     method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+  public final class ComposableLambdaKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
-    ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+    ctor public ComposableLambdaN(int key, boolean tracked, int arity);
     method public int getArity();
     method public int getKey();
     method public R! invoke(java.lang.Object?... args);
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionNKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+  public final class ComposableLambdaNKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
 }
diff --git a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt
@@ -1,13 +1,26 @@
 // Signature format: 3.0
 package androidx.compose {
 
+  @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+    ctor public AbstractApplier(T! root);
+    method public void down(T? node);
+    method public T! getCurrent();
+    method public final T! getRoot();
+    method protected final void move(java.util.List<T>, int from, int to, int count);
+    method protected final void remove(java.util.List<T>, int index, int count);
+    method public void reset();
+    method public void setCurrent(T! p);
+    method public void up();
+    property public T! current;
+  }
+
   public final class ActualAndroidKt {
   }
 
   public final class ActualJvmKt {
   }
 
-  @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+  @androidx.compose.Stable public abstract sealed class Ambient<T> {
     method public final inline T! getCurrent();
     property public final inline T! current;
   }
@@ -25,29 +38,7 @@
     property public final boolean valid;
   }
 
-  public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
-    ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
-    method public android.view.Choreographer getChoreographer();
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-  }
-
-  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
-    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
-    method public android.view.Choreographer getChoreographer();
-    method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
-    property public final androidx.compose.CompositionFrameClock compositionFrameClock;
-    field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
-  }
-
-  public static final class AndroidUiDispatcher.Companion {
-    method public androidx.compose.AndroidUiDispatcher getCurrentThread();
-    method public androidx.compose.AndroidUiDispatcher getMain();
-    property public final androidx.compose.AndroidUiDispatcher CurrentThread;
-    property public final androidx.compose.AndroidUiDispatcher Main;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
-    ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+  @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
     method public void down(N? node);
     method public N! getCurrent();
     method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
     method public void remove(int index, int count);
     method public void reset();
     method public void up();
-    property public final N! current;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
-    method public void end(N?, N? instance, N? parent);
-    method public void insertAt(N?, int index, N? instance);
-    method public void move(N?, int from, int to, int count);
-    method public void removeAt(N?, int index, int count);
-    method public void start(N?, N? instance);
+    property public abstract N! current;
   }
 
   public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
     method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
   }
 
-  @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.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;
+    method public abstract boolean tracked() default true;
   }
 
   @kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> {
+  public final class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
-    method @androidx.compose.InternalComposeApi public final void applyChanges();
-    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 @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
-    method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
-    method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
-    method @androidx.compose.ComposeCompilerApi public final void endDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
-    method @androidx.compose.ComposeCompilerApi public final void endNode();
-    method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
-    method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
-    method public final int getCurrentCompoundKeyHash();
-    method public final boolean getDefaultsInvalid();
-    method public final boolean getInserting();
-    method public final androidx.compose.Recomposer getRecomposer();
-    method public final boolean getSkipping();
-    method public final androidx.compose.SlotTable getSlotTable();
-    method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
-    method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
-    method @androidx.compose.InternalComposeApi public final boolean recompose();
-    method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
-    method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
-    method @androidx.compose.ComposeCompilerApi public final void startDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
-    method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final N! useNode();
+    method @androidx.compose.InternalComposeApi public void applyChanges();
+    method @Deprecated public 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 @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+    method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+    method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+    method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+    method @androidx.compose.ComposeCompilerApi public void endDefaults();
+    method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+    method @androidx.compose.ComposeCompilerApi public void endNode();
+    method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+    method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+    method public androidx.compose.Applier<N> getApplier();
+    method public int getCurrentCompoundKeyHash();
+    method public boolean getDefaultsInvalid();
+    method public boolean getInserting();
+    method public androidx.compose.Recomposer getRecomposer();
+    method public boolean getSkipping();
+    method public androidx.compose.SlotTable getSlotTable();
+    method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+    method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+    method @androidx.compose.InternalComposeApi public boolean recompose();
+    method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+    method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+    method @androidx.compose.ComposeCompilerApi public void startDefaults();
+    method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+    method @androidx.compose.ComposeCompilerApi public void startNode();
+    method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public N! useNode();
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean inserting;
@@ -151,20 +135,11 @@
   }
 
   public final class ComposerKt {
-    method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static androidx.compose.Composer<?> getComposer();
     method public static androidx.compose.Composer<?> getCurrentComposer();
   }
 
-  public final class ComposerUpdater<N, T extends N> {
-    ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
-    method public androidx.compose.Composer<N> getComposer();
-    method public T! getNode();
-    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-  }
-
   @Deprecated public interface ComposerValidator {
     method @Deprecated public boolean changed(int value);
     method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+  public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
     ctor public CompositionCoroutineScope();
     method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
   }
 
-  public interface CompositionFrameClock {
+  @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
     method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionFrameClockKt {
     method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
     method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
     method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
-    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+    method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionKt {
-    method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
     method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
   }
 
   public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
     method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
   }
 
+  public final class EmitKt {
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+  }
+
   public final class ExpectKt {
   }
 
@@ -241,7 +221,7 @@
     method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
     method public void nextFrame();
     method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
-    field public static final androidx.compose.FrameManager! INSTANCE;
+    field public static final androidx.compose.FrameManager INSTANCE;
   }
 
   @androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
     method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
   }
 
-  public final class NullCompilationScope {
-    method public kotlin.Unit getComposer();
+  @Deprecated public final class NullCompilationScope {
+    method @Deprecated public kotlin.Unit getComposer();
     property public final kotlin.Unit composer;
-    field public static final androidx.compose.NullCompilationScope! INSTANCE;
+    field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
   }
 
   public final class ObserveKt {
@@ -316,7 +296,7 @@
     method public void removeValue(V value);
   }
 
-  @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+  @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
     method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
   }
 
@@ -332,12 +312,12 @@
   public final class Recomposer {
     ctor public Recomposer();
     method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public androidx.compose.CompositionFrameClock getFrameClock();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
     method public boolean hasPendingChanges();
-    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
-    property public final androidx.compose.CompositionFrameClock frameClock;
-    field public static final androidx.compose.Recomposer.Companion! Companion;
+    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.Recomposer.Companion Companion;
   }
 
   public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
   }
 
   public final class RecomposerKt {
-    method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
   }
 
   public final class RememberKt {
@@ -430,7 +410,7 @@
     method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
     method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
     property public final int size;
-    field public static final androidx.compose.SlotTable.Companion! Companion;
+    field public static final androidx.compose.SlotTable.Companion Companion;
   }
 
   @androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
     method public abstract Class<?>[] types();
   }
 
-  @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  }
+
+  public final class Updater<T> {
+    ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+    method public androidx.compose.Composer<?> getComposer();
+    method public T! getNode();
+    method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
   }
 
 }
@@ -661,8 +652,8 @@
 
 package androidx.compose.internal {
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
-    ctor public RestartableFunction(int key, boolean tracked);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+    ctor public ComposableLambda(int key, boolean tracked);
     method public int getKey();
     method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
     method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+  public final class ComposableLambdaKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
-    ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+    ctor public ComposableLambdaN(int key, boolean tracked, int arity);
     method public int getArity();
     method public int getKey();
     method public R! invoke(java.lang.Object?... args);
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionNKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+  public final class ComposableLambdaNKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
 }
diff --git a/compose/compose-runtime/api/public_plus_experimental_current.txt b/compose/compose-runtime/api/public_plus_experimental_current.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/public_plus_experimental_current.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_current.txt
@@ -1,13 +1,26 @@
 // Signature format: 3.0
 package androidx.compose {
 
+  @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+    ctor public AbstractApplier(T! root);
+    method public void down(T? node);
+    method public T! getCurrent();
+    method public final T! getRoot();
+    method protected final void move(java.util.List<T>, int from, int to, int count);
+    method protected final void remove(java.util.List<T>, int index, int count);
+    method public void reset();
+    method public void setCurrent(T! p);
+    method public void up();
+    property public T! current;
+  }
+
   public final class ActualAndroidKt {
   }
 
   public final class ActualJvmKt {
   }
 
-  @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+  @androidx.compose.Stable public abstract sealed class Ambient<T> {
     method public final inline T! getCurrent();
     property public final inline T! current;
   }
@@ -25,29 +38,7 @@
     property public final boolean valid;
   }
 
-  public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
-    ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
-    method public android.view.Choreographer getChoreographer();
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-  }
-
-  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
-    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
-    method public android.view.Choreographer getChoreographer();
-    method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
-    property public final androidx.compose.CompositionFrameClock compositionFrameClock;
-    field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
-  }
-
-  public static final class AndroidUiDispatcher.Companion {
-    method public androidx.compose.AndroidUiDispatcher getCurrentThread();
-    method public androidx.compose.AndroidUiDispatcher getMain();
-    property public final androidx.compose.AndroidUiDispatcher CurrentThread;
-    property public final androidx.compose.AndroidUiDispatcher Main;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
-    ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+  @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
     method public void down(N? node);
     method public N! getCurrent();
     method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
     method public void remove(int index, int count);
     method public void reset();
     method public void up();
-    property public final N! current;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
-    method public void end(N?, N? instance, N? parent);
-    method public void insertAt(N?, int index, N? instance);
-    method public void move(N?, int from, int to, int count);
-    method public void removeAt(N?, int index, int count);
-    method public void start(N?, N? instance);
+    property public abstract N! current;
   }
 
   public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
     method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
   }
 
-  @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.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;
+    method public abstract boolean tracked() default true;
   }
 
   @kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> {
+  public final class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
-    method @androidx.compose.InternalComposeApi public final void applyChanges();
-    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 @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
-    method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
-    method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
-    method @androidx.compose.ComposeCompilerApi public final void endDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
-    method @androidx.compose.ComposeCompilerApi public final void endNode();
-    method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
-    method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
-    method public final int getCurrentCompoundKeyHash();
-    method public final boolean getDefaultsInvalid();
-    method public final boolean getInserting();
-    method public final androidx.compose.Recomposer getRecomposer();
-    method public final boolean getSkipping();
-    method public final androidx.compose.SlotTable getSlotTable();
-    method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
-    method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
-    method @androidx.compose.InternalComposeApi public final boolean recompose();
-    method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
-    method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
-    method @androidx.compose.ComposeCompilerApi public final void startDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
-    method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final N! useNode();
+    method @androidx.compose.InternalComposeApi public void applyChanges();
+    method @Deprecated public 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 @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+    method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+    method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+    method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+    method @androidx.compose.ComposeCompilerApi public void endDefaults();
+    method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+    method @androidx.compose.ComposeCompilerApi public void endNode();
+    method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+    method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+    method public androidx.compose.Applier<N> getApplier();
+    method public int getCurrentCompoundKeyHash();
+    method public boolean getDefaultsInvalid();
+    method public boolean getInserting();
+    method public androidx.compose.Recomposer getRecomposer();
+    method public boolean getSkipping();
+    method public androidx.compose.SlotTable getSlotTable();
+    method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+    method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+    method @androidx.compose.InternalComposeApi public boolean recompose();
+    method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+    method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+    method @androidx.compose.ComposeCompilerApi public void startDefaults();
+    method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+    method @androidx.compose.ComposeCompilerApi public void startNode();
+    method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public N! useNode();
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean inserting;
@@ -151,20 +135,11 @@
   }
 
   public final class ComposerKt {
-    method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static androidx.compose.Composer<?> getComposer();
     method public static androidx.compose.Composer<?> getCurrentComposer();
   }
 
-  public final class ComposerUpdater<N, T extends N> {
-    ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
-    method public androidx.compose.Composer<N> getComposer();
-    method public T! getNode();
-    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-  }
-
   @Deprecated public interface ComposerValidator {
     method @Deprecated public boolean changed(int value);
     method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+  public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
     ctor public CompositionCoroutineScope();
     method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
   }
 
-  public interface CompositionFrameClock {
+  @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
     method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionFrameClockKt {
     method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
     method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
     method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
-    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+    method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionKt {
-    method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
     method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
   }
 
   public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
     method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
   }
 
+  public final class EmitKt {
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+  }
+
   public final class ExpectKt {
   }
 
@@ -241,7 +221,7 @@
     method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
     method public void nextFrame();
     method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
-    field public static final androidx.compose.FrameManager! INSTANCE;
+    field public static final androidx.compose.FrameManager INSTANCE;
   }
 
   @androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
     method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
   }
 
-  public final class NullCompilationScope {
-    method public kotlin.Unit getComposer();
+  @Deprecated public final class NullCompilationScope {
+    method @Deprecated public kotlin.Unit getComposer();
     property public final kotlin.Unit composer;
-    field public static final androidx.compose.NullCompilationScope! INSTANCE;
+    field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
   }
 
   public final class ObserveKt {
@@ -316,7 +296,7 @@
     method public void removeValue(V value);
   }
 
-  @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+  @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
     method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
   }
 
@@ -332,12 +312,12 @@
   public final class Recomposer {
     ctor public Recomposer();
     method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public androidx.compose.CompositionFrameClock getFrameClock();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
     method public boolean hasPendingChanges();
-    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
-    property public final androidx.compose.CompositionFrameClock frameClock;
-    field public static final androidx.compose.Recomposer.Companion! Companion;
+    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.Recomposer.Companion Companion;
   }
 
   public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
   }
 
   public final class RecomposerKt {
-    method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
   }
 
   public final class RememberKt {
@@ -430,7 +410,7 @@
     method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
     method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
     property public final int size;
-    field public static final androidx.compose.SlotTable.Companion! Companion;
+    field public static final androidx.compose.SlotTable.Companion Companion;
   }
 
   @androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
     method public abstract Class<?>[] types();
   }
 
-  @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  }
+
+  public final class Updater<T> {
+    ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+    method public androidx.compose.Composer<?> getComposer();
+    method public T! getNode();
+    method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
   }
 
 }
@@ -661,8 +652,8 @@
 
 package androidx.compose.internal {
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
-    ctor public RestartableFunction(int key, boolean tracked);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+    ctor public ComposableLambda(int key, boolean tracked);
     method public int getKey();
     method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
     method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+  public final class ComposableLambdaKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
-    ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+    ctor public ComposableLambdaN(int key, boolean tracked, int arity);
     method public int getArity();
     method public int getKey();
     method public R! invoke(java.lang.Object?... args);
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionNKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+  public final class ComposableLambdaNKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
 }
diff --git a/compose/compose-runtime/api/restricted_0.1.0-dev15.txt b/compose/compose-runtime/api/restricted_0.1.0-dev15.txt
index b097892..aa94c38 100644
--- a/compose/compose-runtime/api/restricted_0.1.0-dev15.txt
+++ b/compose/compose-runtime/api/restricted_0.1.0-dev15.txt
@@ -1,13 +1,26 @@
 // Signature format: 3.0
 package androidx.compose {
 
+  @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+    ctor public AbstractApplier(T! root);
+    method public void down(T? node);
+    method public T! getCurrent();
+    method public final T! getRoot();
+    method protected final void move(java.util.List<T>, int from, int to, int count);
+    method protected final void remove(java.util.List<T>, int index, int count);
+    method public void reset();
+    method public void setCurrent(T! p);
+    method public void up();
+    property public T! current;
+  }
+
   public final class ActualAndroidKt {
   }
 
   public final class ActualJvmKt {
   }
 
-  @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+  @androidx.compose.Stable public abstract sealed class Ambient<T> {
     method public final inline T! getCurrent();
     property public final inline T! current;
   }
@@ -25,29 +38,7 @@
     property public final boolean valid;
   }
 
-  public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
-    ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
-    method public android.view.Choreographer getChoreographer();
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-  }
-
-  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
-    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
-    method public android.view.Choreographer getChoreographer();
-    method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
-    property public final androidx.compose.CompositionFrameClock compositionFrameClock;
-    field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
-  }
-
-  public static final class AndroidUiDispatcher.Companion {
-    method public androidx.compose.AndroidUiDispatcher getCurrentThread();
-    method public androidx.compose.AndroidUiDispatcher getMain();
-    property public final androidx.compose.AndroidUiDispatcher CurrentThread;
-    property public final androidx.compose.AndroidUiDispatcher Main;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
-    ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+  @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
     method public void down(N? node);
     method public N! getCurrent();
     method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
     method public void remove(int index, int count);
     method public void reset();
     method public void up();
-    property public final N! current;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
-    method public void end(N?, N? instance, N? parent);
-    method public void insertAt(N?, int index, N? instance);
-    method public void move(N?, int from, int to, int count);
-    method public void removeAt(N?, int index, int count);
-    method public void start(N?, N? instance);
+    property public abstract N! current;
   }
 
   public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
     method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
   }
 
-  @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.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;
+    method public abstract boolean tracked() default true;
   }
 
   @kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,48 +88,48 @@
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> {
+  public final class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
-    method @androidx.compose.InternalComposeApi public final void applyChanges();
-    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 @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
-    method @androidx.compose.InternalComposeApi 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);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
-    method @androidx.compose.ComposeCompilerApi public final void endDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
-    method @androidx.compose.ComposeCompilerApi public final void endNode();
-    method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
-    method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
-    method public final int getCurrentCompoundKeyHash();
-    method public final boolean getDefaultsInvalid();
-    method public final boolean getInserting();
-    method public final androidx.compose.Recomposer getRecomposer();
-    method public final boolean getSkipping();
-    method public final androidx.compose.SlotTable getSlotTable();
-    method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
-    method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
-    method @androidx.compose.InternalComposeApi public final boolean recompose();
-    method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
-    method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
-    method @androidx.compose.ComposeCompilerApi public final void startDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
-    method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
-    method @kotlin.PublishedApi internal final void updateValue(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final N! useNode();
+    method @androidx.compose.InternalComposeApi public void applyChanges();
+    method @Deprecated public 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 @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+    method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+    method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method @kotlin.PublishedApi internal <T> T! consume(androidx.compose.Ambient<T> key);
+    method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+    method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+    method @androidx.compose.ComposeCompilerApi public void endDefaults();
+    method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+    method @androidx.compose.ComposeCompilerApi public void endNode();
+    method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+    method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+    method public androidx.compose.Applier<N> getApplier();
+    method public int getCurrentCompoundKeyHash();
+    method public boolean getDefaultsInvalid();
+    method public boolean getInserting();
+    method public androidx.compose.Recomposer getRecomposer();
+    method public boolean getSkipping();
+    method public androidx.compose.SlotTable getSlotTable();
+    method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+    method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+    method @androidx.compose.InternalComposeApi public boolean recompose();
+    method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+    method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+    method @androidx.compose.ComposeCompilerApi public void startDefaults();
+    method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+    method @androidx.compose.ComposeCompilerApi public void startNode();
+    method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+    method @kotlin.PublishedApi internal void updateValue(Object? value);
+    method @androidx.compose.ComposeCompilerApi public N! useNode();
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean inserting;
@@ -154,7 +138,8 @@
 
   public final class ComposerKt {
     method @kotlin.PublishedApi internal static inline <N, T> T! cache(androidx.compose.Composer<N>, boolean valid = true, kotlin.jvm.functions.Function0<? extends T> block);
-    method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static androidx.compose.Composer<?> getComposer();
     method public static androidx.compose.Composer<?> getCurrentComposer();
     field @kotlin.PublishedApi internal static final androidx.compose.OpaqueKey ambientMap;
     field @kotlin.PublishedApi internal static final int ambientMapKey = 202; // 0xca
@@ -170,16 +155,6 @@
     field @kotlin.PublishedApi internal static final int referenceKey = 206; // 0xce
   }
 
-  public final class ComposerUpdater<N, T extends N> {
-    ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
-    method public androidx.compose.Composer<N> getComposer();
-    method public T! getNode();
-    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-  }
-
   @Deprecated public interface ComposerValidator {
     method @Deprecated public boolean changed(int value);
     method @Deprecated public <T> boolean changed(T? value);
@@ -190,26 +165,26 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+  public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
     ctor public CompositionCoroutineScope();
     method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
   }
 
-  public interface CompositionFrameClock {
+  @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
     method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionFrameClockKt {
     method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
     method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
     method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
-    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+    method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionKt {
-    method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
     method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
   }
 
   public interface CompositionLifecycleObserver {
@@ -238,6 +213,11 @@
     method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
   }
 
+  public final class EmitKt {
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+  }
+
   public final class ExpectKt {
   }
 
@@ -256,7 +236,7 @@
     method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
     method public void nextFrame();
     method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
-    field public static final androidx.compose.FrameManager! INSTANCE;
+    field public static final androidx.compose.FrameManager INSTANCE;
   }
 
   @androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -308,10 +288,10 @@
     method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
   }
 
-  public final class NullCompilationScope {
-    method public kotlin.Unit getComposer();
+  @Deprecated public final class NullCompilationScope {
+    method @Deprecated public kotlin.Unit getComposer();
     property public final kotlin.Unit composer;
-    field public static final androidx.compose.NullCompilationScope! INSTANCE;
+    field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
   }
 
   public final class ObserveKt {
@@ -346,7 +326,7 @@
     method public void onLeave();
   }
 
-  @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+  @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
     method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
   }
 
@@ -362,12 +342,12 @@
   public final class Recomposer {
     ctor public Recomposer();
     method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public androidx.compose.CompositionFrameClock getFrameClock();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
     method public boolean hasPendingChanges();
-    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
-    property public final androidx.compose.CompositionFrameClock frameClock;
-    field public static final androidx.compose.Recomposer.Companion! Companion;
+    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.Recomposer.Companion Companion;
   }
 
   public static final class Recomposer.Companion {
@@ -376,7 +356,7 @@
   }
 
   public final class RecomposerKt {
-    method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
   }
 
   public final class RememberKt {
@@ -460,7 +440,7 @@
     method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
     method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
     property public final int size;
-    field public static final androidx.compose.SlotTable.Companion! Companion;
+    field public static final androidx.compose.SlotTable.Companion Companion;
   }
 
   @androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -553,7 +533,18 @@
     method public abstract Class<?>[] types();
   }
 
-  @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  }
+
+  public final class Updater<T> {
+    ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+    method public androidx.compose.Composer<?> getComposer();
+    method public T! getNode();
+    method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
   }
 
 }
@@ -693,8 +684,8 @@
 
 package androidx.compose.internal {
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
-    ctor public RestartableFunction(int key, boolean tracked);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+    ctor public ComposableLambda(int key, boolean tracked);
     method public int getKey();
     method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
     method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -718,22 +709,22 @@
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+  public final class ComposableLambdaKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
-    ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+    ctor public ComposableLambdaN(int key, boolean tracked, int arity);
     method public int getArity();
     method public int getKey();
     method public R! invoke(java.lang.Object?... args);
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionNKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+  public final class ComposableLambdaNKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
 }
diff --git a/compose/compose-runtime/api/restricted_current.txt b/compose/compose-runtime/api/restricted_current.txt
index b097892..aa94c38 100644
--- a/compose/compose-runtime/api/restricted_current.txt
+++ b/compose/compose-runtime/api/restricted_current.txt
@@ -1,13 +1,26 @@
 // Signature format: 3.0
 package androidx.compose {
 
+  @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+    ctor public AbstractApplier(T! root);
+    method public void down(T? node);
+    method public T! getCurrent();
+    method public final T! getRoot();
+    method protected final void move(java.util.List<T>, int from, int to, int count);
+    method protected final void remove(java.util.List<T>, int index, int count);
+    method public void reset();
+    method public void setCurrent(T! p);
+    method public void up();
+    property public T! current;
+  }
+
   public final class ActualAndroidKt {
   }
 
   public final class ActualJvmKt {
   }
 
-  @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+  @androidx.compose.Stable public abstract sealed class Ambient<T> {
     method public final inline T! getCurrent();
     property public final inline T! current;
   }
@@ -25,29 +38,7 @@
     property public final boolean valid;
   }
 
-  public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
-    ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
-    method public android.view.Choreographer getChoreographer();
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-  }
-
-  public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
-    method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
-    method public android.view.Choreographer getChoreographer();
-    method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
-    property public final androidx.compose.CompositionFrameClock compositionFrameClock;
-    field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
-  }
-
-  public static final class AndroidUiDispatcher.Companion {
-    method public androidx.compose.AndroidUiDispatcher getCurrentThread();
-    method public androidx.compose.AndroidUiDispatcher getMain();
-    property public final androidx.compose.AndroidUiDispatcher CurrentThread;
-    property public final androidx.compose.AndroidUiDispatcher Main;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
-    ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+  @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
     method public void down(N? node);
     method public N! getCurrent();
     method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
     method public void remove(int index, int count);
     method public void reset();
     method public void up();
-    property public final N! current;
-  }
-
-  @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
-    method public void end(N?, N? instance, N? parent);
-    method public void insertAt(N?, int index, N? instance);
-    method public void move(N?, int from, int to, int count);
-    method public void removeAt(N?, int index, int count);
-    method public void start(N?, N? instance);
+    property public abstract N! current;
   }
 
   public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
     method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
   }
 
-  @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.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;
+    method public abstract boolean tracked() default true;
   }
 
   @kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,48 +88,48 @@
     method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
   }
 
-  public class Composer<N> {
+  public final class Composer<N> {
     ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
-    method @androidx.compose.InternalComposeApi public final void applyChanges();
-    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 @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
-    method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
-    method @androidx.compose.InternalComposeApi 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);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
-    method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
-    method @androidx.compose.ComposeCompilerApi public final void endDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
-    method @androidx.compose.ComposeCompilerApi public final void endNode();
-    method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
-    method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
-    method public final int getCurrentCompoundKeyHash();
-    method public final boolean getDefaultsInvalid();
-    method public final boolean getInserting();
-    method public final androidx.compose.Recomposer getRecomposer();
-    method public final boolean getSkipping();
-    method public final androidx.compose.SlotTable getSlotTable();
-    method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
-    method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
-    method @androidx.compose.InternalComposeApi public final boolean recompose();
-    method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
-    method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
-    method @androidx.compose.ComposeCompilerApi public final void startDefaults();
-    method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
-    method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
-    method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
-    method @kotlin.PublishedApi internal final void updateValue(Object? value);
-    method @androidx.compose.ComposeCompilerApi public final N! useNode();
+    method @androidx.compose.InternalComposeApi public void applyChanges();
+    method @Deprecated public 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 @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+    method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+    method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+    method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+    method @kotlin.PublishedApi internal <T> T! consume(androidx.compose.Ambient<T> key);
+    method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+    method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+    method @androidx.compose.ComposeCompilerApi public void endDefaults();
+    method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+    method @androidx.compose.ComposeCompilerApi public void endNode();
+    method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+    method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+    method public androidx.compose.Applier<N> getApplier();
+    method public int getCurrentCompoundKeyHash();
+    method public boolean getDefaultsInvalid();
+    method public boolean getInserting();
+    method public androidx.compose.Recomposer getRecomposer();
+    method public boolean getSkipping();
+    method public androidx.compose.SlotTable getSlotTable();
+    method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+    method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+    method @androidx.compose.InternalComposeApi public boolean recompose();
+    method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+    method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+    method @androidx.compose.ComposeCompilerApi public void startDefaults();
+    method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+    method @androidx.compose.ComposeCompilerApi public void startNode();
+    method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+    method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+    method @kotlin.PublishedApi internal void updateValue(Object? value);
+    method @androidx.compose.ComposeCompilerApi public N! useNode();
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean inserting;
@@ -154,7 +138,8 @@
 
   public final class ComposerKt {
     method @kotlin.PublishedApi internal static inline <N, T> T! cache(androidx.compose.Composer<N>, boolean valid = true, kotlin.jvm.functions.Function0<? extends T> block);
-    method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+    method @Deprecated public static androidx.compose.Composer<?> getComposer();
     method public static androidx.compose.Composer<?> getCurrentComposer();
     field @kotlin.PublishedApi internal static final androidx.compose.OpaqueKey ambientMap;
     field @kotlin.PublishedApi internal static final int ambientMapKey = 202; // 0xca
@@ -170,16 +155,6 @@
     field @kotlin.PublishedApi internal static final int referenceKey = 206; // 0xce
   }
 
-  public final class ComposerUpdater<N, T extends N> {
-    ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
-    method public androidx.compose.Composer<N> getComposer();
-    method public T! getNode();
-    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
-    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
-  }
-
   @Deprecated public interface ComposerValidator {
     method @Deprecated public boolean changed(int value);
     method @Deprecated public <T> boolean changed(T? value);
@@ -190,26 +165,26 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
-  public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+  public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
     ctor public CompositionCoroutineScope();
     method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
   }
 
-  public interface CompositionFrameClock {
+  @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
     method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
-    method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionFrameClockKt {
     method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
     method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
     method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
-    method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+    method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
   }
 
   public final class CompositionKt {
-    method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
     method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+    method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
   }
 
   public interface CompositionLifecycleObserver {
@@ -238,6 +213,11 @@
     method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
   }
 
+  public final class EmitKt {
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+    method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+  }
+
   public final class ExpectKt {
   }
 
@@ -256,7 +236,7 @@
     method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
     method public void nextFrame();
     method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
-    field public static final androidx.compose.FrameManager! INSTANCE;
+    field public static final androidx.compose.FrameManager INSTANCE;
   }
 
   @androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -308,10 +288,10 @@
     method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
   }
 
-  public final class NullCompilationScope {
-    method public kotlin.Unit getComposer();
+  @Deprecated public final class NullCompilationScope {
+    method @Deprecated public kotlin.Unit getComposer();
     property public final kotlin.Unit composer;
-    field public static final androidx.compose.NullCompilationScope! INSTANCE;
+    field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
   }
 
   public final class ObserveKt {
@@ -346,7 +326,7 @@
     method public void onLeave();
   }
 
-  @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+  @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
     method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
   }
 
@@ -362,12 +342,12 @@
   public final class Recomposer {
     ctor public Recomposer();
     method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public androidx.compose.CompositionFrameClock getFrameClock();
+    method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
     method public boolean hasPendingChanges();
-    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
-    property public final androidx.compose.CompositionFrameClock frameClock;
-    field public static final androidx.compose.Recomposer.Companion! Companion;
+    method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+    property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+    field public static final androidx.compose.Recomposer.Companion Companion;
   }
 
   public static final class Recomposer.Companion {
@@ -376,7 +356,7 @@
   }
 
   public final class RecomposerKt {
-    method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
   }
 
   public final class RememberKt {
@@ -460,7 +440,7 @@
     method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
     method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
     property public final int size;
-    field public static final androidx.compose.SlotTable.Companion! Companion;
+    field public static final androidx.compose.SlotTable.Companion Companion;
   }
 
   @androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -553,7 +533,18 @@
     method public abstract Class<?>[] types();
   }
 
-  @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+  }
+
+  public final class Updater<T> {
+    ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+    method public androidx.compose.Composer<?> getComposer();
+    method public T! getNode();
+    method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+    method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+    method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+    method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
   }
 
 }
@@ -693,8 +684,8 @@
 
 package androidx.compose.internal {
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
-    ctor public RestartableFunction(int key, boolean tracked);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+    ctor public ComposableLambda(int key, boolean tracked);
     method public int getKey();
     method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
     method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -718,22 +709,22 @@
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+  public final class ComposableLambdaKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
-  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
-    ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+  @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+    ctor public ComposableLambdaN(int key, boolean tracked, int arity);
     method public int getArity();
     method public int getKey();
     method public R! invoke(java.lang.Object?... args);
     method public void update(Object block);
   }
 
-  public final class RestartableFunctionNKt {
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
-    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+  public final class ComposableLambdaNKt {
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
 }
diff --git a/compose/compose-runtime/build.gradle b/compose/compose-runtime/build.gradle
index 6d0d947..3b3989b 100644
--- a/compose/compose-runtime/build.gradle
+++ b/compose/compose-runtime/build.gradle
@@ -39,6 +39,7 @@
         commonMain.dependencies {
             implementation(KOTLIN_STDLIB_COMMON)
             implementation(KOTLIN_COROUTINES_CORE_COMMON)
+            api project(':compose:compose-dispatch')
         }
         jvmMain.dependencies {
             implementation(KOTLIN_STDLIB)
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml
index e48051b..2759840 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml
@@ -26,7 +26,11 @@
         android:requestLegacyExternalStorage="true"
         android:debuggable="false"
         tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
+
         <activity
             android:name=".ComposeActivity"/>
     </application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/CustomTreeCompositionSamples.kt b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/CustomTreeCompositionSamples.kt
new file mode 100644
index 0000000..32c5959
--- /dev/null
+++ b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/CustomTreeCompositionSamples.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.AbstractApplier
+import androidx.compose.Composable
+import androidx.compose.Composition
+import androidx.compose.ExperimentalComposeApi
+import androidx.compose.Recomposer
+import androidx.compose.compositionFor
+import androidx.compose.emit
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.compose.state
+
+@Suppress("unused")
+@OptIn(ExperimentalComposeApi::class)
+@Sampled
+fun CustomTreeComposition() {
+    // Provided we have a tree with a node base type like the following
+    abstract class Node {
+        val children = mutableListOf<Node>()
+    }
+
+    // We would implement an Applier class like the following, which would teach compose how to
+    // manage a tree of Nodes.
+    class NodeApplier(root: Node) : AbstractApplier<Node>(root) {
+        override fun insert(index: Int, instance: Node) {
+            current.children.add(index, instance)
+        }
+
+        override fun remove(index: Int, count: Int) {
+            current.children.remove(index, count)
+        }
+
+        override fun move(from: Int, to: Int, count: Int) {
+            current.children.move(from, to, count)
+        }
+    }
+
+    // A function like the following could be created to create a composition provided a root Node.
+    fun Node.setContent(content: @Composable () -> Unit): Composition {
+        return compositionFor(this, NodeApplier(this), Recomposer.current()).also {
+            setContent(content)
+        }
+    }
+
+    // assuming we have Node sub-classes like "TextNode" and "GroupNode"
+    class TextNode : Node() {
+        var text: String = ""
+        var onClick: () -> Unit = {}
+    }
+    class GroupNode : Node()
+
+    // Composable equivalents could be created
+    @Composable fun Text(text: String, onClick: () -> Unit = {}) {
+        emit<TextNode, NodeApplier>(::TextNode) {
+            set(text) { this.text = it }
+            set(onClick) { this.onClick = it }
+        }
+    }
+
+    @Composable fun Group(content: @Composable () -> Unit) {
+        emit<GroupNode, NodeApplier>(::GroupNode, {}, content)
+    }
+
+    // and then a sample tree could be composed:
+    fun runApp(root: GroupNode) {
+        root.setContent {
+            var count by state { 0 }
+            Group {
+                Text("Count: $count")
+                Text("Increment") { count++ }
+            }
+        }
+    }
+}
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 d870aa60..0bd4b6a 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
@@ -19,15 +19,14 @@
 import android.widget.TextView
 import androidx.compose.Ambient
 import androidx.compose.Composable
+import androidx.compose.ComposableContract
 import androidx.compose.CompositionReference
 import androidx.compose.ExperimentalComposeApi
 import androidx.compose.Providers
 import androidx.compose.Recomposer
 import androidx.compose.StructurallyEqual
-import androidx.compose.Untracked
 import androidx.compose.ambientOf
 import androidx.compose.compositionReference
-import androidx.compose.escapeCompose
 import androidx.compose.invalidate
 import androidx.compose.remember
 import androidx.compose.staticAmbientOf
@@ -35,7 +34,7 @@
 import androidx.test.filters.MediumTest
 import androidx.ui.core.LayoutNode
 import androidx.ui.core.subcomposeInto
-import androidx.ui.node.UiComposer
+import androidx.ui.viewinterop.emitView
 import org.junit.After
 import org.junit.Rule
 import org.junit.Test
@@ -64,11 +63,9 @@
 @RunWith(AndroidJUnit4::class)
 class AmbientTests : BaseComposeTest() {
 
-    val composer: UiComposer get() = error("should not be called")
-
     @Composable
     fun Text(value: String, id: Int = 100) {
-        TextView(id = id, text = value)
+        emitView(::TextView) { it.id = id; it.text = value; }
     }
 
     @Composable
@@ -511,18 +508,17 @@
     }
 
     @Composable fun deferredSubCompose(block: @Composable () -> Unit): () -> Unit {
-        val container = remember { escapeCompose { LayoutNode() } }
+        val container = remember { LayoutNode() }
         val ref = Ref<CompositionReference>()
         narrowInvalidateForReference(ref = ref)
         return {
             @OptIn(ExperimentalComposeApi::class)
-            // TODO(b/150390669): Review use of @Untracked
+            // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
             subcomposeInto(
-                activityRule.activity,
                 container,
                 Recomposer.current(),
                 ref.value
-            ) @Untracked {
+            ) @ComposableContract(tracked = false) {
                 block()
             }
         }
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 1a1235e..eb10e2f 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
@@ -27,15 +27,16 @@
 import androidx.compose.Choreographer
 import androidx.compose.ChoreographerFrameCallback
 import androidx.compose.Composable
+import androidx.compose.ComposableContract
 import androidx.compose.Composition
 import androidx.compose.ExperimentalComposeApi
 import androidx.compose.FrameManager
 import androidx.compose.Looper
+import androidx.compose.Providers
 import androidx.compose.Recomposer
-import androidx.compose.Untracked
 import androidx.compose.compositionReference
-import androidx.compose.escapeCompose
 import androidx.compose.remember
+import androidx.ui.core.ContextAmbient
 import androidx.ui.core.LayoutNode
 import androidx.ui.core.setViewContent
 import androidx.ui.core.subcomposeInto
@@ -116,37 +117,28 @@
 
     fun compose(
         composable: @Composable () -> Unit
-    ) = UiTester(
-        activity,
-        composable
-    )
-
-    fun composeEmittables(
-        composable: @Composable () -> Unit
-    ) = EmittableTester(
+    ) = ComposeTester(
         activity,
         composable
     )
 
     @Composable
     fun subCompose(block: @Composable () -> Unit) {
-        val container =
-            remember { escapeCompose { LayoutNode() } }
+        val container = remember { LayoutNode() }
         val reference = compositionReference()
-        // TODO(b/150390669): Review use of @Untracked
+        // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
         @OptIn(ExperimentalComposeApi::class)
         subcomposeInto(
-            activityRule.activity,
             container,
             Recomposer.current(),
             reference
-        ) @Untracked {
+        ) @ComposableContract(tracked = false) {
             block()
         }
     }
 }
 
-sealed class ComposeTester(val activity: Activity, val composable: @Composable () -> Unit) {
+class ComposeTester(val activity: Activity, val composable: @Composable () -> Unit) {
     inner class ActiveTest(val activity: Activity, val composition: Composition) {
         fun then(block: ActiveTest.(activity: Activity) -> Unit): ActiveTest {
             activity.waitForAFrame()
@@ -161,7 +153,15 @@
         }
     }
 
-    abstract fun initialComposition(composable: @Composable () -> Unit): Composition
+    private fun initialComposition(composable: @Composable () -> Unit): Composition {
+        return activity.show {
+            Providers(
+                ContextAmbient provides activity
+            ) {
+                composable()
+            }
+        }
+    }
 
     fun then(block: ComposeTester.(activity: Activity) -> Unit): ActiveTest {
         val composition = initialComposition(composable)
@@ -172,24 +172,3 @@
         return ActiveTest(activity, composition)
     }
 }
-
-class EmittableTester(activity: Activity, composable: @Composable () -> Unit) :
-    ComposeTester(activity, composable) {
-    override fun initialComposition(composable: @Composable () -> Unit): Composition {
-        var composition: Composition? = null
-        activity.uiThread {
-            FrameManager.nextFrame()
-            composition = activity.setEmittableContent(composable)
-        }
-        return composition!!
-    }
-}
-
-class UiTester(activity: Activity, composable: @Composable () -> Unit) :
-    ComposeTester(activity, composable) {
-    override fun initialComposition(composable: @Composable () -> Unit): Composition {
-        return activity.show {
-            composable()
-        }
-    }
-}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt
index ecba4dd..6c22dd6 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt
@@ -18,6 +18,8 @@
 
 import android.os.HandlerThread
 import androidx.compose.Composable
+import androidx.compose.ComposableContract
+import androidx.compose.ExperimentalComposeApi
 import androidx.compose.FrameManager
 import androidx.compose.Handler
 import androidx.compose.clearRoots
@@ -52,7 +54,8 @@
 
         var initializationCount = 0
         var commitCount = 0
-        val composable = @Composable {
+        @OptIn(ExperimentalComposeApi::class)
+        val composable = @Composable @ComposableContract(tracked = false) {
             onActive { initializationCount++ }
             onCommit { commitCount++ }
         }
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 5c06179..c346cf9 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
@@ -31,7 +31,6 @@
 import androidx.compose.frames.open
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
 import junit.framework.TestCase.assertEquals
 import junit.framework.TestCase.assertFalse
 import org.junit.After
@@ -128,8 +127,6 @@
 @RunWith(AndroidJUnit4::class)
 class ModelViewTests : BaseComposeTest() {
 
-    val composer: UiComposer get() = error("should not be called")
-
     @After
     fun teardown() {
         clearRoots()
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposerCompat.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposerCompat.kt
deleted file mode 100644
index dffa262..0000000
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposerCompat.kt
+++ /dev/null
@@ -1,31 +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.compose.test
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
-    "This property should not be called directly. It is only used by the compiler.",
-    replaceWith = ReplaceWith("currentComposer")
-)
-val composer: EmittableComposer
-    get() = error(
-        "This property should not be called directly. It is only used by the compiler."
-    )
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt
index 16af8c0..aad6292 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt
@@ -17,7 +17,9 @@
 package androidx.compose.test
 
 import androidx.compose.Composable
+import androidx.compose.ComposableContract
 import androidx.compose.Composition
+import androidx.compose.ExperimentalComposeApi
 import androidx.compose.clearRoots
 import androidx.compose.onActive
 import androidx.compose.onPreCommit
@@ -44,7 +46,8 @@
     fun testDisposeComposition() {
         val log = mutableListOf<String>()
 
-        val composable = @Composable {
+        @OptIn(ExperimentalComposeApi::class)
+        val composable = @Composable @ComposableContract(tracked = false) {
             onPreCommit {
                 log.add("onPreCommit")
                 onDispose {
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 e15243b..841cc15 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
@@ -34,7 +34,6 @@
 import androidx.compose.state
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
 import junit.framework.TestCase.assertEquals
 import junit.framework.TestCase.assertTrue
 import org.junit.After
@@ -46,8 +45,6 @@
 @RunWith(AndroidJUnit4::class)
 class EffectsTests : BaseComposeTest() {
 
-    val composer: UiComposer get() = error("should not be called")
-
     @After
     fun teardown() {
         clearRoots()
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt
index f814f7e..0be9e33 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt
@@ -13,199 +13,55 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@file:OptIn(ComposeCompilerApi::class, ExperimentalComposeApi::class)
 package androidx.compose.test
 
-import android.app.Activity
-import android.content.Context
 import android.view.View
-import android.view.ViewGroup
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
+import android.widget.TextView
+import android.widget.Button
+import android.widget.LinearLayout
 import androidx.compose.Composable
-import androidx.compose.ComposeCompilerApi
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
-import androidx.compose.Composition
-import androidx.compose.ExperimentalComposeApi
-import androidx.compose.FrameManager
-import androidx.compose.Recomposer
-import androidx.compose.SlotTable
-import androidx.compose.compositionFor
-import androidx.ui.node.UiComposer
+import androidx.ui.viewinterop.emitView
 
-interface Emittable {
-    fun emitInsertAt(index: Int, instance: Emittable)
-    fun emitRemoveAt(index: Int, count: Int)
-    fun emitMove(from: Int, to: Int, count: Int)
-}
-
-internal class EmittableApplyAdapter : ApplyAdapter<Any> {
-    override fun Any.start(instance: Any) {}
-    override fun Any.insertAt(index: Int, instance: Any) {
-        when (this) {
-            is ViewGroup -> insertAt(index, instance)
-            is Emittable -> emitInsertAt(index, instance as Emittable)
-            else -> error("unexpected node")
-        }
-    }
-
-    override fun Any.removeAt(index: Int, count: Int) {
-        when (this) {
-            is ViewGroup -> removeViews(index, count)
-            is Emittable -> emitRemoveAt(index, count)
-            else -> error("unexpected node")
-        }
-    }
-
-    override fun Any.move(from: Int, to: Int, count: Int) {
-        when (this) {
-            is ViewGroup -> {
-                if (from > to) {
-                    var currentFrom = from
-                    var currentTo = to
-                    repeat(count) {
-                        val view = getChildAt(currentFrom)
-                        removeViewAt(currentFrom)
-                        addView(view, currentTo)
-                        currentFrom++
-                        currentTo++
-                    }
-                } else {
-                    repeat(count) {
-                        val view = getChildAt(from)
-                        removeViewAt(from)
-                        addView(view, to - 1)
-                    }
-                }
-            }
-            is Emittable -> {
-                emitMove(from, to, count)
-            }
-            else -> error("unexpected node")
-        }
-    }
-
-    override fun Any.end(instance: Any, parent: Any) {}
-}
-
-class EmittableComposer(
-    val context: Context,
-    val root: Any,
-    slotTable: SlotTable,
-    recomposer: Recomposer
-) : Composer<Any>(
-    slotTable,
-    Applier(
-        root,
-        EmittableApplyAdapter()
-    ),
-    recomposer
+@Composable
+fun TextView(
+    id: Int = 0,
+    text: String = "",
+    onClickListener: View.OnClickListener? = null
 ) {
-    init {
-        FrameManager.ensureStarted()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    fun <T : View> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: (context: Context) -> T,
-        update: ViewUpdater<T>.() -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor(context).also { emitNode(it) }
-        else useNode() as T
-        ViewUpdater(this, node).update()
-        endNode()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    fun <T : ViewGroup> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: (context: Context) -> T,
-        update: ViewUpdater<T>.() -> Unit,
-        children: () -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor(context).also { emitNode(it) }
-        else useNode() as T
-        ViewUpdater(this, node).update()
-        children()
-        endNode()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    fun <T : Emittable> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: () -> T,
-        update: ViewUpdater<T>.() -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor().also { emitNode(it) }
-        else useNode() as T
-        ViewUpdater(this, node).update()
-        endNode()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    fun <T : Emittable> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: () -> T,
-        update: ViewUpdater<T>.() -> Unit,
-        children: () -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor().also { emitNode(it) }
-        else useNode() as T
-        ViewUpdater(this, node).update()
-        children()
-        endNode()
+    emitView(::TextView) {
+        if (id != 0) it.id = id
+        it.text = text
+        if (onClickListener != null) it.setOnClickListener(onClickListener)
     }
 }
 
-typealias ViewUpdater<T> = ComposerUpdater<Any, T>
-
-class ComponentNodeScope { val composer: UiComposer get() = error("should not get called") }
-class EmittableScope { val composer: EmittableComposer get() = error("should not get called") }
-
-class Node(val name: String, var value: String = "") : Emittable {
-    val children = mutableListOf<Node>()
-
-    override fun emitInsertAt(index: Int, instance: Emittable) {
-        children.add(index, instance as Node)
-    }
-
-    override fun emitRemoveAt(index: Int, count: Int) {
-        repeat(count) { children.removeAt(index) }
-    }
-
-    override fun emitMove(from: Int, to: Int, count: Int) {
-        if (from > to) {
-            repeat(count) {
-                children.add(to + it, children.removeAt(from))
-            }
-        } else if (from < to) {
-            repeat(count) {
-                children.add(to - 1, children.removeAt(from))
-            }
-        }
+@Composable
+fun Button(
+    id: Int = 0,
+    text: String = "",
+    onClickListener: View.OnClickListener? = null
+) {
+    emitView(::Button) {
+        if (id != 0) it.id = id
+        it.text = text
+        if (onClickListener != null) it.setOnClickListener(onClickListener)
     }
 }
 
-fun Activity.setEmittableContent(content: @Composable () -> Unit): Composition {
-    val root = Node("Root")
-    val composition = compositionFor(root, Recomposer.current()) { slotTable, recomposer ->
-        EmittableComposer(
-            this,
-            root,
-            slotTable,
-            recomposer
-        )
-    }
-    composition.setContent(content)
-    return composition
+@Composable
+fun LinearLayout(
+    id: Int = 0,
+    orientation: Int = LinearLayout.VERTICAL,
+    onClickListener: View.OnClickListener? = null,
+    children: @Composable () -> Unit
+) {
+    emitView(
+        ::LinearLayout,
+        {
+            if (id != 0) it.id = id
+            if (onClickListener != null) it.setOnClickListener(onClickListener)
+            it.orientation = orientation
+        },
+        children
+    )
 }
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt
index e03fbc7..3fed09d 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt
@@ -17,7 +17,6 @@
 
 package androidx.compose.test
 
-import android.content.Context
 import android.widget.LinearLayout
 import android.widget.TextView
 import androidx.compose.Composable
@@ -28,7 +27,6 @@
 import androidx.compose.setValue
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
 import junit.framework.TestCase
 import org.junit.After
 import org.junit.Rule
@@ -39,8 +37,6 @@
 @RunWith(AndroidJUnit4::class)
 class NewCodeGenTests : BaseComposeTest() {
 
-    val composer: UiComposer get() = error("should not be called")
-
     @After
     fun teardown() {
         clearRoots()
@@ -276,56 +272,4 @@
             }
         }
     }
-
-    @Test
-    fun testViewClassWithCtorParametersInvocation() {
-        val tvId = 749
-
-        class MyTextView(context: Context) : TextView(context) {
-            constructor(context: Context, someText: String) : this(context) {
-                text = someText
-            }
-        }
-
-        var hello by mutableStateOf("Hello world!")
-        compose {
-            // <MyTextView someText = hello />
-            key(hello) {
-                MyTextView(id = tvId, someText = hello)
-            }
-        }.then { activity ->
-            val tv = activity.findViewById(tvId) as TextView
-            TestCase.assertEquals("Hello world!", tv.text)
-
-            hello = "Salutations!"
-        }.then { activity ->
-            val tv = activity.findViewById(tvId) as TextView
-            TestCase.assertEquals("Salutations!", tv.text)
-        }
-    }
-
-    @Test
-    fun testViewClassWithMutableCtorParameter() {
-        val tvId = 749
-
-        class MyTextView(context: Context, var someValue: String) : TextView(context)
-
-        var hello by mutableStateOf("Hello world!")
-        var value by mutableStateOf("Unmodified")
-        compose {
-            // <MyTextView someText = hello />
-            MyTextView(id = tvId, someValue = value, text = hello)
-        }.then { activity ->
-            val tv = activity.findViewById(tvId) as MyTextView
-            TestCase.assertEquals("Hello world!", tv.text)
-            TestCase.assertEquals("Unmodified", tv.someValue)
-
-            hello = "Salutations!"
-            value = "Modified"
-        }.then { activity ->
-            val tv = activity.findViewById(tvId) as MyTextView
-            TestCase.assertEquals("Salutations!", tv.text)
-            TestCase.assertEquals("Modified", tv.someValue)
-        }
-    }
 }
\ No newline at end of file
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 5e3d7c8..b7a3fe0 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
@@ -31,7 +31,6 @@
 import androidx.compose.setValue
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
 import junit.framework.TestCase.assertEquals
 import junit.framework.TestCase.assertFalse
 import junit.framework.TestCase.assertNotSame
@@ -44,8 +43,6 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class RecomposerTests : BaseComposeTest() {
-    val composer: UiComposer get() = error("should not be called")
-
     @After
     fun teardown() {
         clearRoots()
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 cdf26f7..3e0a8eb 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
@@ -24,7 +24,6 @@
 import androidx.compose.mutableStateOf
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
 import junit.framework.TestCase
 import org.junit.After
 import org.junit.Rule
@@ -38,8 +37,6 @@
 @RunWith(AndroidJUnit4::class)
 class RestartTests : BaseComposeTest() {
 
-    val composer: UiComposer get() = error("should not be called")
-
     @After
     fun teardown() {
         clearRoots()
diff --git a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt b/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt
index b261f5b..0de8c00 100644
--- a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt
+++ b/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose
 
+import androidx.compose.dispatch.AndroidUiDispatcher
+import androidx.compose.dispatch.MonotonicFrameClock
 import androidx.core.os.HandlerCompat
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
@@ -65,27 +67,25 @@
 // TODO: Our host-side tests still grab the Android actuals based on SDK stubs that return null.
 // Satisfy their dependencies.
 private val MainAndroidUiDispatcher by lazy {
-    if (Looper.getMainLooper() != null) AndroidUiDispatcher.Main
+    if (Looper.getMainLooper() != null) androidx.compose.dispatch.AndroidUiDispatcher.Main
     else Dispatchers.Main
 }
 
-private object MainDispatcherCompositionFrameClock : CompositionFrameClock {
+private object MainDispatcherFrameClock : MonotonicFrameClock {
     override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R =
         withContext(Dispatchers.Main) {
             onFrame(System.nanoTime())
         }
 }
 
-private val MainAndroidCompositionFrameClock by lazy {
-    if (Looper.getMainLooper() != null) AndroidUiDispatcher.Main.compositionFrameClock
-    else MainDispatcherCompositionFrameClock
+private val MainAndroidFrameClock by lazy {
+    if (Looper.getMainLooper() != null) AndroidUiDispatcher.Main.frameClock
+    else MainDispatcherFrameClock
 }
 
-internal actual fun mainThreadCompositionDispatcher(): CoroutineDispatcher =
-    MainAndroidUiDispatcher
+internal actual fun mainThreadCompositionDispatcher(): CoroutineDispatcher = MainAndroidUiDispatcher
 
-internal actual fun mainThreadCompositionFrameClock(): CompositionFrameClock =
-    MainAndroidCompositionFrameClock
+internal actual fun mainThreadFrameClock(): MonotonicFrameClock = MainAndroidFrameClock
 
 internal actual object Trace {
     actual fun beginSection(name: String) = android.os.Trace.beginSection(name)
diff --git a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiDispatcher.kt b/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiDispatcher.kt
deleted file mode 100644
index 85a8311..0000000
--- a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiDispatcher.kt
+++ /dev/null
@@ -1,154 +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.compose
-
-import android.view.Choreographer
-import androidx.core.os.HandlerCompat
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Runnable
-import kotlinx.coroutines.runBlocking
-import kotlin.coroutines.CoroutineContext
-
-/**
- * A [CoroutineDispatcher] that will perform dispatch during [choreographer]'s animation frame
- * stage. Suspending will always wait until the next frame.
- */
-@OptIn(ExperimentalStdlibApi::class)
-class AndroidUiDispatcher private constructor(
-    val choreographer: Choreographer,
-    private val handler: android.os.Handler
-) : CoroutineDispatcher() {
-
-    // Guards all properties in this class
-    private val lock = Any()
-
-    private val toRunTrampolined = ArrayDeque<Runnable>()
-    private var toRunOnFrame = mutableListOf<ChoreographerFrameCallback>()
-    private var spareToRunOnFrame = mutableListOf<ChoreographerFrameCallback>()
-    private var scheduledTrampolineDispatch = false
-    private var scheduledFrameDispatch = false
-
-    private val dispatchCallback = object : ChoreographerFrameCallback, java.lang.Runnable {
-        override fun run() {
-            performTrampolineDispatch()
-            synchronized(lock) {
-                if (toRunOnFrame.isEmpty()) {
-                    choreographer.removeFrameCallback(this)
-                    scheduledFrameDispatch = false
-                }
-            }
-        }
-
-        override fun doFrame(frameTimeNanos: Long) {
-            handler.removeCallbacks(this)
-            performTrampolineDispatch()
-            performFrameDispatch(frameTimeNanos)
-        }
-    }
-
-    private fun nextTask(): Runnable? = synchronized(lock) {
-        toRunTrampolined.removeFirstOrNull()
-    }
-
-    private fun performTrampolineDispatch() {
-        do {
-            var task = nextTask()
-            while (task != null) {
-                task.run()
-                task = nextTask()
-            }
-        } while (
-            // We don't dispatch holding the lock so that other tasks can get in on our
-            // trampolining time slice, but once we're done, make sure nothing added a new task
-            // before we set scheduledDispatch = false, which would prevent the next dispatch
-            // from being correctly scheduled. Loop to run these stragglers now.
-            synchronized(lock) {
-                if (toRunTrampolined.isEmpty()) {
-                    scheduledTrampolineDispatch = false
-                    false
-                } else true
-            }
-        )
-    }
-
-    private fun performFrameDispatch(frameTimeNanos: Long) {
-        val toRun = synchronized(lock) {
-            if (!scheduledFrameDispatch) return
-            scheduledFrameDispatch = false
-            val result = toRunOnFrame
-            toRunOnFrame = spareToRunOnFrame
-            spareToRunOnFrame = result
-            result
-        }
-        for (i in 0 until toRun.size) {
-            // This callback can't throw, see AndroidUiCompositionFrameClock
-            toRun[i].doFrame(frameTimeNanos)
-        }
-        toRun.clear()
-    }
-
-    internal fun postFrameCallback(callback: ChoreographerFrameCallback) {
-        synchronized(lock) {
-            toRunOnFrame.add(callback)
-            if (!scheduledFrameDispatch) {
-                scheduledFrameDispatch = true
-                choreographer.postFrameCallback(dispatchCallback)
-            }
-        }
-    }
-
-    internal fun removeFrameCallback(callback: ChoreographerFrameCallback) {
-        synchronized(lock) {
-            toRunOnFrame.remove(callback)
-        }
-    }
-
-    val compositionFrameClock: CompositionFrameClock = AndroidUiCompositionFrameClock(choreographer)
-
-    override fun dispatch(context: CoroutineContext, block: Runnable) {
-        synchronized(lock) {
-            toRunTrampolined.addLast(block)
-            if (!scheduledTrampolineDispatch) {
-                scheduledTrampolineDispatch = true
-                handler.post(dispatchCallback)
-                if (!scheduledFrameDispatch) {
-                    scheduledFrameDispatch = true
-                    choreographer.postFrameCallback(dispatchCallback)
-                }
-            }
-        }
-    }
-
-    companion object {
-        val Main by lazy {
-            AndroidUiDispatcher(
-                if (isMainThread()) Choreographer.getInstance()
-                else runBlocking(Dispatchers.Main) { Choreographer.getInstance() },
-                HandlerCompat.createAsync(Looper.getMainLooper())
-            )
-        }
-
-        private val currentThread = ThreadLocal {
-            AndroidUiDispatcher(
-                Choreographer.getInstance(),
-                HandlerCompat.createAsync(Looper.myLooper() ?: error("no Looper on this thread"))
-            )
-        }
-        val CurrentThread: AndroidUiDispatcher get() = currentThread.get()
-    }
-}
\ No newline at end of file
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 c71b9c7..2dc5cf2 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
@@ -54,7 +54,7 @@
  *
  * @sample androidx.compose.samples.consumeAmbient
  */
-@Immutable
+@Stable
 sealed class Ambient<T> constructor(defaultFactory: (() -> T)? = null) {
     @Suppress("UNCHECKED_CAST")
     internal val defaultValueHolder = LazyValueHolder(defaultFactory)
@@ -80,7 +80,7 @@
  * @see Ambient
  * @see Providers
  */
-@Immutable
+@Stable
 abstract class ProvidableAmbient<T> internal constructor(defaultFactory: (() -> T)?) :
     Ambient<T> (defaultFactory) {
 
@@ -119,7 +119,6 @@
  *
  * @see staticAmbientOf
  */
-@Immutable
 internal class StaticProvidableAmbient<T>(defaultFactory: (() -> T)?) :
     ProvidableAmbient<T>(defaultFactory) {
 
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt
index 8bd88c9..6408ee5 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt
@@ -17,62 +17,116 @@
 package androidx.compose
 
 /**
- * An adapter that performs tree based operations on some tree startNode N without requiring a specific base type for N
+ * An Applier is responsible for applying the tree-based operations that get emitted during a
+ * composition. Every [Composer] has an [Applier] which it uses to [emit].
+ *
+ * A custom [Applier] implementation will be needed in order to utilize Compose to build and
+ * maintain a tree of a novel type.
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @see AbstractApplier
+ * @see compositionFor
+ * @see Composer
+ * @see emit
  */
 @ExperimentalComposeApi
-interface ApplyAdapter<N> {
-    fun N.start(instance: N)
-    fun N.insertAt(index: Int, instance: N)
-    fun N.removeAt(index: Int, count: Int)
-    fun N.move(from: Int, to: Int, count: Int)
-    fun N.end(instance: N, parent: N)
+interface Applier<N> {
+    /**
+     * The node that operations will be applied on at any given time. It is expected that the
+     * value of this property will change as [down] and [up] are called.
+     */
+    val current: N
+
+    /**
+     * Indicates that the applier is getting traversed "down" the tree. When this gets called,
+     * [node] is expected to be a child of [current], and after this operation, [node] is
+     * expected to be the new [current].
+     */
+    fun down(node: N)
+
+    /**
+     * Indicates that the applier is getting traversed "up" the tree. After this operation
+     * completes, the [current] should return the "parent" of the [current] node at the beginning
+     * of this operation.
+     */
+    fun up()
+
+    /**
+     * Indicates that [instance] should be inserted as a child to [current] at [index]
+     */
+    fun insert(index: Int, instance: N)
+
+    /**
+     * Indicates that the children of [current] from [index] to [index] + [count] should be removed.
+     */
+    fun remove(index: Int, count: Int)
+
+    /**
+     * Indicates that the children of [current] from [from] to [from] + [count] should be moved
+     * to [to] + [count].
+     *
+     * The [to] index is related to the position before the change, so, for example, to move an
+     * element at position 1 to after the element at position 2, [from] should be `1` and [to]
+     * should be `3`. If the elements were A B C D E, calling `move(1, 3, 1)` would result in the
+     * elements being reordered to A C B D E.
+     */
+    fun move(from: Int, to: Int, count: Int)
+
+    /**
+     * Reset the applier's state
+     */
+    fun reset()
 }
 
 /**
- * A helper class to apply changes to a tree with startNode types N given an apply adapter for type N
+ * An abstract [Applier] implementation that builds the tree "top down".
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @see Applier
+ * @see compositionFor
+ * @see Composer
+ * @see emit
  */
 @ExperimentalComposeApi
-class Applier<N>(root: N, private val adapter: ApplyAdapter<N>) {
-    private val stack = Stack<N>()
-    private var _current: N = root
+abstract class AbstractApplier<T>(val root: T) : Applier<T> {
+    private val stack = mutableListOf<T>()
+    override var current: T = root
 
-    val current: N get() = _current
-
-    fun down(node: N) {
-        stack.push(current)
-        _current = node
-        with(adapter) {
-            current.start(node)
-        }
+    override fun down(node: T) {
+        stack.add(current)
+        current = node
     }
 
-    fun up() {
-        val node = _current
-        _current = stack.pop()
-        with(adapter) {
-            current.end(node, current)
-        }
+    override fun up() {
+        current = stack.removeAt(stack.size - 1)
     }
 
-    fun insert(index: Int, instance: N) {
-        with(adapter) {
-            current.insertAt(index, instance)
-        }
-    }
-
-    fun remove(index: Int, count: Int) {
-        with(adapter) {
-            current.removeAt(index, count)
-        }
-    }
-
-    fun move(from: Int, to: Int, count: Int) {
-        with(adapter) {
-            current.move(from, to, count)
-        }
-    }
-
-    fun reset() {
+    override fun reset() {
         stack.clear()
+        current = root
+    }
+
+    protected fun MutableList<T>.remove(index: Int, count: Int) {
+        if (count == 1) {
+            removeAt(index)
+        } else {
+            subList(index, index + count).clear()
+        }
+    }
+
+    protected fun MutableList<T>.move(from: Int, to: Int, count: Int) {
+        if (count == 1) {
+            val fromEl = get(from)
+            val toEl = set(to, fromEl)
+            set(from, toEl)
+        } else {
+            val subView = subList(from, from + count)
+            val subCopy = subView.toMutableList()
+            val dest = if (from > to) to else (to - count)
+            subView.clear()
+            addAll(dest, subCopy)
+        }
     }
 }
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt
index 8622a5f..7327e90 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlin.coroutines.Continuation
 
@@ -30,7 +31,7 @@
  */
 internal class BroadcastFrameClock(
     private val onNewAwaiters: (() -> Unit)? = null
-) : CompositionFrameClock {
+) : MonotonicFrameClock {
 
     private data class FrameAwaiter<R>(val onFrame: (Long) -> R, val continuation: Continuation<R>)
 
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt
index 34e3f4e..5bc48cb 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt
@@ -34,9 +34,6 @@
 @MustBeDocumented
 @Retention(AnnotationRetention.BINARY)
 @Target(
-    // not currently used
-    AnnotationTarget.CLASS,
-
     // function declarations
     // @Composable fun Foo() { ... }
     // lambda expressions
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
index 91aec87..b8e52b4 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
@@ -24,14 +24,18 @@
  * 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
+ * @param restartable if 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
+ * @param readonly if true, 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..
+ *
+ * @param tracked if false, this will disable lambda optimizations such as tracking execution of
+ * composable function expressions or remembering a function expression value based on its
+ * capture variables. This flag is only meaningful when applied to @Composable lambda expressions
  */
 @MustBeDocumented
 @Retention(AnnotationRetention.BINARY)
@@ -41,5 +45,6 @@
 )
 annotation class ComposableContract(
     val restartable: Boolean = true,
-    val readonly: Boolean = false
+    val readonly: Boolean = false,
+    val tracked: Boolean = true
 )
\ 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 03677e6..23d3903 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
@@ -38,7 +38,7 @@
     "This property should not be called directly. It is only used by the compiler.",
     replaceWith = ReplaceWith("currentComposer")
 )
-internal val composer: Composer<*> get() = error(
+val composer: Composer<*> get() = error(
     "This property should not be called directly. It is only used by the compiler."
 )
 
@@ -330,11 +330,11 @@
     fun <T> changed(value: T): Boolean
 }
 
-// TODO(lmr): this could be named MutableTreeComposer
+// TODO(b/159074030): Consider removing type parameter
 /**
  * Implementation of a composer for mutable tree.
  */
-open class Composer<N>(
+class Composer<N>(
     /**
      * Backing storage for the composition
      */
@@ -343,7 +343,8 @@
     /**
      * An adapter that applies changes to the tree using the Applier abstraction.
      */
-    private val applier: Applier<N>,
+    @ComposeCompilerApi
+    val applier: Applier<N>,
 
     /**
      * Manager for scheduling recompositions.
@@ -351,6 +352,9 @@
     @ExperimentalComposeApi
     val recomposer: Recomposer
 ) {
+    init {
+        FrameManager.ensureStarted()
+    }
     private val changes = mutableListOf<Change<N>>()
     private val lifecycleObservers = HashMap<
         CompositionLifecycleObserverHolder,
@@ -404,7 +408,8 @@
     private var insertAnchor: Anchor = insertTable.anchor(0)
     private val insertFixups = mutableListOf<Change<N>>()
 
-    protected fun composeRoot(block: () -> Unit) {
+    @InternalComposeApi
+    fun composeRoot(block: () -> Unit) {
         startRoot()
         startGroup(invocationKey, invocation)
         block()
@@ -731,35 +736,13 @@
      * does not have the provided key a node with that key is scanned for and moved into the
      * current position if found, if no such node is found the composition switches into insert
      * mode and a the node is scheduled to be inserted at the current location.
-     *
-     * @param key the key for the node.
      */
     @ComposeCompilerApi
-    fun startNode(key: Any) {
-        start(nodeKey, key, true, null)
+    fun startNode() {
+        start(nodeKey, null, true, null)
         nodeExpected = true
     }
 
-    // Deprecated
-    @ComposeCompilerApi
-    fun <T : N> emitNode(factory: () -> T) {
-        validateNodeExpected()
-        if (inserting) {
-            val insertIndex = nodeIndexStack.peek()
-            // The pending is the pending information for where the node is being inserted.
-            // pending will be null here when the parent was inserted too.
-            groupNodeCount++
-            recordFixup { applier, slots, _ ->
-                val node = factory()
-                slots.node = node
-                applier.insert(insertIndex, node)
-                applier.down(node)
-            }
-        } else {
-            recordDown(reader.node)
-        }
-    }
-
     /**
      * Schedule a node to be created and inserted at the current location. This is only valid to
      * call when the composer is inserting.
@@ -787,13 +770,14 @@
      * inserting.
      */
     @ComposeCompilerApi
-    fun emitNode(node: N) {
+    fun emitNode(node: Any) {
         validateNodeExpected()
         require(inserting) { "emitNode() called when not inserting" }
         val insertIndex = nodeIndexStack.peek()
         // see emitNode
         groupNodeCount++
-        writer.node = node
+        @Suppress("UNCHECKED_CAST")
+        writer.node = node as N
         recordApplierOperation { applier, _, _ ->
             applier.insert(insertIndex, node)
             applier.down(node)
@@ -1198,7 +1182,7 @@
             if (collectKeySources)
                 recordSourceKeyInfo(key)
             when {
-                isNode -> writer.startNode(dataKey)
+                isNode -> writer.startNode(null)
                 data != null -> writer.startData(key, dataKey, data)
                 else -> writer.startGroup(key, dataKey)
             }
@@ -1267,7 +1251,7 @@
                 ensureWriter()
                 writer.beginInsert()
                 val insertLocation = writer.current
-                if (isNode) writer.startNode(dataKey) else writer.startGroup(key, dataKey)
+                if (isNode) writer.startNode(null) else writer.startGroup(key, dataKey)
                 insertAnchor = writer.anchor(insertLocation)
                 val insertKeyInfo = KeyInfo(key, -1, 0, -1, 0, writer.parentGroup)
                 pending.registerInsert(insertKeyInfo, nodeIndex - pending.startIndex)
@@ -2232,7 +2216,7 @@
 }
 
 @Suppress("UNCHECKED_CAST")
-/*inline */ class ComposerUpdater<N, T : N>(val composer: Composer<N>, val node: T) {
+/*inline */ class Updater<T>(val composer: Composer<*>, val node: T) {
     inline fun set(
         value: Int,
         /*crossinline*/
@@ -2284,6 +2268,12 @@
 //            if (!inserting) composer.apply(value, appliedBlock)
         }
     }
+
+    inline fun reconcile(
+        block: T.() -> Unit
+    ) {
+        node.block()
+    }
 }
 
 /**
@@ -2425,10 +2415,18 @@
 private fun Boolean.asInt() = if (this) 1 else 0
 private fun Int.asBool() = this != 0
 
+@Deprecated(
+    "This no longer has any effect"
+)
 object NullCompilationScope {
     val composer = Unit
 }
 
+@Suppress("DEPRECATION")
+@Deprecated(
+    "This no longer has any effect",
+    ReplaceWith("block()")
+)
 inline fun <T> escapeCompose(block: NullCompilationScope.() -> T) = NullCompilationScope.block()
 
 @Composable
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt
index bccf965..3469410 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt
@@ -52,6 +52,7 @@
  * @param parent The parent composition reference, if applicable. Default is null.
  * @param composerFactory The factory used to created a [Composer] to be used by the composition.
  */
+@Deprecated("Use the compositionFor(...) overload that accepts an Applier<N>")
 fun compositionFor(
     container: Any,
     recomposer: Recomposer,
@@ -76,6 +77,7 @@
  * @param parent The parent composition reference, if applicable. Default is null.
  * @param composerFactory The factory used to created a [Composer] to be used by the composition.
  */
+@Suppress("DEPRECATION")
 @Deprecated(
     "Specify the Recomposer explicitly",
     ReplaceWith(
@@ -90,6 +92,46 @@
 ): Composition = compositionFor(container, Recomposer.current(), parent, composerFactory)
 
 /**
+ * This method is the way to initiate a composition. Optionally, a [parent]
+ * [CompositionReference] can be provided to make the composition behave as a sub-composition of
+ * the parent.
+ *
+ * It is important to call [Composition.dispose] whenever this [key] is no longer needed in
+ * order to release resources.
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @param key The object this composition will be tied to. Only one [Composition] will be created
+ * for a given [key]. If the same [key] is passed in subsequent calls, the same [Composition]
+ * instance will be returned.
+ * @param applier The [Applier] instance to be used in the composition.
+ * @param recomposer The [Recomposer] instance to be used for composition.
+ * @param parent The parent composition reference, if applicable. Default is null.
+ * @param onCreated A function which will be executed only when the Composition is created.
+ *
+ * @see Applier
+ * @see Composition
+ * @see Recomposer
+ */
+@ExperimentalComposeApi
+fun compositionFor(
+    key: Any,
+    applier: Applier<*>,
+    recomposer: Recomposer,
+    parent: CompositionReference? = null,
+    onCreated: () -> Unit = {}
+): Composition = Compositions.findOrCreate(key) {
+    CompositionImpl(
+        recomposer,
+        parent,
+        composerFactory = { slots, rcmpsr -> Composer(slots, applier, rcmpsr) },
+        onDispose = { Compositions.onDisposed(key) }
+    ).also {
+        onCreated()
+    }
+}
+
+/**
  * @param parent An optional reference to the parent composition.
  * @param composerFactory A function to create a composer object, for use during composition
  * @param onDispose A callback to be triggered when [dispose] is called.
@@ -98,7 +140,7 @@
     private val recomposer: Recomposer,
     parent: CompositionReference?,
     composerFactory: (SlotTable, Recomposer) -> Composer<*>,
-    private val onDispose: (() -> Unit)
+    private val onDispose: () -> Unit
 ) : Composition {
     private val slotTable: SlotTable = SlotTable()
     private val composer: Composer<*> = composerFactory(slotTable, recomposer).also {
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt
index 6a2e1c8..58651a3 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt
@@ -17,27 +17,16 @@
 // TODO(b/158105080): make part of ComposeRuntime
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
+import androidx.compose.dispatch.withFrameMillis as withFrameMillisDispatch
+
 /**
  * Provides a time source for display frames for use in composition.
  * This may be used for matching timing with the refresh rate of a display
  * or otherwise synchronizing with a desired frame rate of composition updates.
  */
-interface CompositionFrameClock {
-    /**
-     * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
-     * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
-     * [onFrame].
-     *
-     * `frameTimeNanos` should be used when calculating animation time deltas from frame to frame
-     * as it may be normalized to the target time for the frame, not necessarily a direct,
-     * "now" value.
-     *
-     * The time base of the value provided by [withFrameNanos] is implementation defined.
-     * Time values provided are monotonically increasing; after a call to [withFrameNanos]
-     * completes it must not provide the same value again for a subsequent call.
-     */
-    suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R
-
+@Deprecated("Moved and renamed to MonotonicFrameClock")
+interface CompositionFrameClock : MonotonicFrameClock {
     /**
      * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
      * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
@@ -70,10 +59,17 @@
  * [CompositionFrameClock.withFrameMillis] completes it must not provide the same value again for
  * a subsequent call.
  */
-@Suppress("UnnecessaryLambdaCreation")
+@Deprecated(
+    "CompositionFrameClock moved and renamed to MonotonicFrameClock",
+    ReplaceWith(
+        "withFrameMillis(onFrame)",
+        "androidx.compose.dispatch.withFrameMillis"
+    )
+)
+@Suppress("UnnecessaryLambdaCreation", "DEPRECATION")
 suspend inline fun <R> CompositionFrameClock.withFrameMillis(
     crossinline onFrame: (frameTimeMillis: Long) -> R
-): R = withFrameNanos { onFrame(it / 1_000_000L) }
+): R = withFrameMillisDispatch(onFrame)
 
 /**
  * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
@@ -88,6 +84,7 @@
  * Time values provided are monotonically increasing; after a call to [awaitFrameNanos]
  * completes it must not provide the same value again for a subsequent call.
  */
+@Suppress("DEPRECATION")
 @Deprecated(
     "renamed to withFrameMillis",
     ReplaceWith("withFrameMillis(onFrame)", "androidx.compose.withFrameMillis")
@@ -106,6 +103,7 @@
  * Time values returned are monotonically increasing; after a call to [awaitFrameNanos]
  * returns it must not return the same value again for a subsequent call.
  */
+@Suppress("DEPRECATION")
 @Deprecated(
     "callers will resume after missing the frame on most dispatchers",
     ReplaceWith("withFrameNanos { it }")
@@ -122,6 +120,7 @@
  * Time values returned are monotonically increasing; after a call to [awaitFrameMillis]
  * returns it must not return the same value again for a subsequent call.
  */
+@Suppress("DEPRECATION")
 @Deprecated(
     "callers will resume after missing the frame on most dispatchers",
     ReplaceWith("withFrameMillis { it }", "androidx.compose.withFrameMillis")
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Emit.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Emit.kt
new file mode 100644
index 0000000..c26ae9b
--- /dev/null
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Emit.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ComposeCompilerApi::class, ExperimentalComposeApi::class)
+package androidx.compose
+
+/**
+ * Emits a node into the composition of type [T].
+ *
+ * This function will throw a runtime exception if [E] is not a subtype of the applier of the
+ * [currentComposer].
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @param ctor A function which will create a new instance of [T]. This function is NOT
+ * guaranteed to be called in place.
+ * @param update A function to perform updates on the node. This will run every time emit is
+ * executed. This function is called in place and will be inlined.
+ *
+ * @see Updater
+ * @see Applier
+ * @see emit
+ * @see compositionFor
+ */
+@OptIn(ComposeCompilerApi::class)
+@Composable inline fun <T : Any, reified E : Applier<*>> emit(
+    noinline ctor: () -> T,
+    update: Updater<T>.() -> Unit
+) {
+    require(currentComposer.applier is E)
+    currentComposer.startNode()
+    val node = if (currentComposer.inserting)
+        ctor().also { currentComposer.emitNode(it) }
+    else
+        @Suppress("UNCHECKED_CAST")
+        currentComposer.useNode() as T
+    Updater(currentComposer, node).update()
+    currentComposer.endNode()
+}
+
+// TODO(lmr): make assert more informative
+// TODO(lmr): consider invoking children manually
+// TODO(lmr): consider ComposableContract for this
+/**
+ * Emits a node into the composition of type [T]. Nodes emitted inside of [children] will become
+ * children of the emitted node.
+ *
+ * This function will throw a runtime exception if [E] is not a subtype of the applier of the
+ * [currentComposer].
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @param ctor A function which will create a new instance of [T]. This function is NOT
+ * guaranteed to be called in place.
+ * @param update A function to perform updates on the node. This will run every time emit is
+ * executed. This function is called in place and will be inlined.
+ * @param children the composable content that will emit the "children" of this node.
+ *
+ * @see Updater
+ * @see Applier
+ * @see emit
+ * @see compositionFor
+ */
+@OptIn(ComposeCompilerApi::class)
+@Composable
+inline fun <T : Any, reified E : Applier<*>> emit(
+    noinline ctor: () -> T,
+    update: Updater<T>.() -> Unit,
+    children: @Composable () -> Unit
+) {
+    require(currentComposer.applier is E)
+    currentComposer.startNode()
+    val node = if (currentComposer.inserting)
+        ctor().also { currentComposer.emitNode(it) }
+    else
+        @Suppress("UNCHECKED_CAST")
+        currentComposer.useNode() as T
+    Updater(currentComposer, node).update()
+    children()
+    currentComposer.endNode()
+}
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt
index 9fca4c6..af83486 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
 import kotlinx.coroutines.CoroutineDispatcher
 
 // TODO(aelias): Mark the typealiases internal when https://youtrack.jetbrains.com/issue/KT-36695 is fixed.
@@ -99,7 +100,7 @@
 }
 
 internal expect fun mainThreadCompositionDispatcher(): CoroutineDispatcher
-internal expect fun mainThreadCompositionFrameClock(): CompositionFrameClock
+internal expect fun mainThreadFrameClock(): MonotonicFrameClock
 
 @MustBeDocumented
 @Retention(AnnotationRetention.BINARY)
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt
index 14991fa..62260a5 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt
@@ -17,6 +17,7 @@
 @file:OptIn(InternalComposeApi::class)
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,7 +35,7 @@
  * [frameClock] is used to align changes with display frames.
  */
 suspend fun withRunningRecomposer(
-    frameClock: CompositionFrameClock,
+    frameClock: MonotonicFrameClock,
     block: suspend CoroutineScope.(recomposer: Recomposer) -> Unit
 ): Unit = coroutineScope {
     val recomposer = Recomposer()
@@ -82,7 +83,7 @@
             }
         }
     }
-    val frameClock: CompositionFrameClock get() = broadcastFrameClock
+    val frameClock: MonotonicFrameClock get() = broadcastFrameClock
 
     /**
      * Await the invalidation of any associated [Composer]s, recompose them, and apply their
@@ -94,7 +95,7 @@
      * This method never returns. Cancel the calling [CoroutineScope] to stop.
      */
     suspend fun runRecomposeAndApplyChanges(
-        frameClock: CompositionFrameClock
+        frameClock: MonotonicFrameClock
     ): Nothing {
         coroutineScope {
             recomposeAndApplyChanges(this, frameClock, Long.MAX_VALUE)
@@ -114,7 +115,7 @@
      */
     suspend fun recomposeAndApplyChanges(
         applyCoroutineScope: CoroutineScope,
-        frameClock: CompositionFrameClock,
+        frameClock: MonotonicFrameClock,
         frameCount: Long
     ) {
         var framesRemaining = frameCount
@@ -200,8 +201,8 @@
 
     private class CompositionCoroutineScopeImpl(
         override val coroutineContext: CoroutineContext,
-        frameClock: CompositionFrameClock
-    ) : CompositionCoroutineScope(), CompositionFrameClock by frameClock
+        frameClock: MonotonicFrameClock
+    ) : CompositionCoroutineScope(), MonotonicFrameClock by frameClock
 
     /**
      * Implementation note: we launch effects undispatched so they can begin immediately during
@@ -330,7 +331,7 @@
                     mainRecomposer = it
                     @OptIn(ExperimentalCoroutinesApi::class)
                     mainScope.launch(start = CoroutineStart.UNDISPATCHED) {
-                        it.runRecomposeAndApplyChanges(mainThreadCompositionFrameClock())
+                        it.runRecomposeAndApplyChanges(mainThreadFrameClock())
                     }
                 }
             }
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt
index 24fdd18..cc65b2d 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt
@@ -18,6 +18,7 @@
 @file:OptIn(InternalComposeApi::class)
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.cancel
@@ -43,12 +44,12 @@
 
 /**
  * A [CoroutineScope] used for launching [side effects][launchInComposition] of a composition
- * that also permits [awaiting][CompositionFrameClock.withFrameNanos] the next presentation
+ * that also permits [awaiting][MonotonicFrameClock.withFrameNanos] the next presentation
  * frame of the composition. This can be useful for performing the next action of an animation
  * while the effect is still present in the composition.
  */
 // TODO Make this an interface once it doesn't experience compiler issues
-abstract class CompositionCoroutineScope : CoroutineScope, CompositionFrameClock {
+abstract class CompositionCoroutineScope : CoroutineScope, MonotonicFrameClock {
     // This method deliberately shadows the awaitFrame method from kotlinx-coroutines-android
     // to redirect usage to the CompositionFrameClock API in effect blocks.
     @Suppress("RedundantSuspendModifier")
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt
index 9fe14cf..f77a3fd 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt
@@ -27,4 +27,9 @@
     AnnotationTarget.FUNCTION
 )
 @ExperimentalComposeApi
+@Deprecated(
+    "This is now implemented as a composable contract",
+    ReplaceWith("@ComposableContract(tracked=false)", "androidx.compose.ComposableContract"),
+    DeprecationLevel.ERROR
+)
 annotation class Untracked
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/RestartableFunction.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/ComposableLambda.kt
similarity index 97%
rename from compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/RestartableFunction.kt
rename to compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/ComposableLambda.kt
index 234c85a..0a72f697 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/RestartableFunction.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/ComposableLambda.kt
@@ -44,7 +44,7 @@
  */
 @Stable
 @ComposeCompilerApi
-class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16,
+class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16,
         P17, P18, R>(
             val key: Int,
             private val tracked: Boolean
@@ -1140,20 +1140,20 @@
     this == null || !this.valid || this == other || this.anchor == other.anchor
 
 @ComposeCompilerApi
-private typealias RFunction = RestartableFunction<Any, Any, Any, Any, Any, Any, Any, Any, Any, Any,
+private typealias CLambda = ComposableLambda<Any, Any, Any, Any, Any, Any, Any, Any, Any, Any,
         Any, Any, Any, Any, Any, Any, Any, Any, Any>
 
 @Suppress("unused")
 @ComposeCompilerApi
-fun restartableFunction(composer: Composer<*>, key: Int, tracked: Boolean, block: Any): RFunction {
+fun composableLambda(composer: Composer<*>, key: Int, tracked: Boolean, block: Any): CLambda {
     composer.startReplaceableGroup(key)
     val slot = composer.nextSlot()
     val result = if (slot === SlotTable.EMPTY) {
-        val value = RFunction(key, tracked)
+        val value = CLambda(key, tracked)
         composer.updateValue(value)
         value
     } else {
-        slot as RFunction
+        slot as CLambda
     }
     result.update(block)
     composer.endReplaceableGroup()
@@ -1162,5 +1162,5 @@
 
 @Suppress("unused")
 @ComposeCompilerApi
-fun restartableFunctionInstance(key: Int, tracked: Boolean, block: Any) =
-    RFunction(key, tracked).apply { update(block) }
+fun composableLambdaInstance(key: Int, tracked: Boolean, block: Any) =
+    CLambda(key, tracked).apply { update(block) }
diff --git a/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt b/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt
index d70f5c6..e9a170d 100644
--- a/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt
+++ b/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
 import javax.swing.JComponent
 import javax.swing.SwingUtilities
 import kotlinx.coroutines.CoroutineDispatcher
@@ -131,15 +132,14 @@
     keyInfo.clear()
 }
 
-private object MainCompositionFrameClock : CompositionFrameClock {
+private object MainDispatcherFrameClock : MonotonicFrameClock {
     override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R =
         withContext(Dispatchers.Main) {
             onFrame(java.lang.System.nanoTime())
         }
 }
 
-internal actual fun mainThreadCompositionFrameClock(): CompositionFrameClock =
-    MainCompositionFrameClock
+internal actual fun mainThreadFrameClock(): MonotonicFrameClock = MainDispatcherFrameClock
 
 internal actual fun mainThreadCompositionDispatcher(): CoroutineDispatcher =
     Dispatchers.Main
diff --git a/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/RestartableFunctionN.kt b/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/ComposableLambdaN.kt
similarity index 91%
rename from compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/RestartableFunctionN.kt
rename to compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/ComposableLambdaN.kt
index f1396ed..6dba142 100644
--- a/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/RestartableFunctionN.kt
+++ b/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/ComposableLambdaN.kt
@@ -29,7 +29,7 @@
 
 @Stable
 @ComposeCompilerApi
-class RestartableFunctionN<R>(
+class ComposableLambdaN<R>(
     val key: Int,
     private val tracked: Boolean,
     override val arity: Int
@@ -93,22 +93,22 @@
 
 @Suppress("unused")
 @ComposeCompilerApi
-fun restartableFunctionN(
+fun composableLambdaN(
     composer: Composer<*>,
     key: Int,
     tracked: Boolean,
     arity: Int,
     block: Any
-): RestartableFunctionN<*> {
+): ComposableLambdaN<*> {
     composer.startReplaceableGroup(key)
     val slot = composer.nextSlot()
     val result = if (slot === SlotTable.EMPTY) {
-        val value = RestartableFunctionN<Any>(key, tracked, arity)
+        val value = ComposableLambdaN<Any>(key, tracked, arity)
         composer.updateValue(value)
         value
     } else {
         @Suppress("UNCHECKED_CAST")
-        slot as RestartableFunctionN<Any>
+        slot as ComposableLambdaN<Any>
     }
     result.update(block)
     composer.endReplaceableGroup()
@@ -117,9 +117,9 @@
 
 @Suppress("unused")
 @ComposeCompilerApi
-fun restartableFunctionNInstance(
+fun composableLambdaNInstance(
     key: Int,
     tracked: Boolean,
     arity: Int,
     block: Any
-): RestartableFunctionN<*> = RestartableFunctionN<Any>(key, tracked, arity).apply { update(block) }
+): ComposableLambdaN<*> = ComposableLambdaN<Any>(key, tracked, arity).apply { update(block) }
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt
index 3fd352b..0a69115 100644
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt
@@ -17,14 +17,16 @@
 @file:OptIn(ExperimentalComposeApi::class, InternalComposeApi::class)
 package androidx.compose
 
+import androidx.compose.dispatch.MonotonicFrameClock
 import androidx.compose.mock.Contact
 import androidx.compose.mock.ContactModel
 import androidx.compose.mock.MockComposeScope
-import androidx.compose.mock.MockViewComposer
+import androidx.compose.mock.MockViewListValidator
 import androidx.compose.mock.MockViewValidator
 import androidx.compose.mock.Point
 import androidx.compose.mock.Report
 import androidx.compose.mock.View
+import androidx.compose.mock.ViewApplier
 import androidx.compose.mock.contact
 import androidx.compose.mock.edit
 import androidx.compose.mock.linear
@@ -36,7 +38,6 @@
 import androidx.compose.mock.selectContact
 import androidx.compose.mock.skip
 import androidx.compose.mock.text
-import androidx.compose.mock.validate
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
@@ -61,11 +62,11 @@
     @Test
     fun testComposeAModel() {
         val model = testModel()
-        val myComposer = compose {
+        val result = compose {
             selectContact(model)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 linear {
                     text("Filter:")
@@ -86,13 +87,13 @@
     @Test
     fun testRecomposeWithoutChanges() {
         val model = testModel()
-        val myComposer = compose {
+        val result = compose {
             selectContact(model)
         }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             selectContact(model)
         }
     }
@@ -102,12 +103,12 @@
         val model =
             testModel(mutableListOf(bob, jon))
         var changed = {}
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             selectContact(model)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 skip()
                 linear {
@@ -122,9 +123,9 @@
 
         model.add(steve, after = bob)
         changed()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 skip()
                 linear {
@@ -149,16 +150,16 @@
             )
         )
         var changed = {}
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             selectContact(model)
         }
 
         model.move(steve, after = jon)
         changed()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 skip()
                 linear {
@@ -183,16 +184,16 @@
             )
         )
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             selectContact(model)
         }
 
         model.filter = "Jon"
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 skip()
                 linear {
@@ -213,11 +214,11 @@
             clark_reports_to_lois
         )
 
-        val myComposer = compose {
+        val result = compose {
             reportsReport(reports)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             reportsReport(reports)
         }
     }
@@ -230,7 +231,7 @@
             clark_reports_to_lois
         )
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             reportsReport(reports)
         }
@@ -241,9 +242,9 @@
             rob_reports_to_alice
         )
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             reportsReport(reports)
         }
     }
@@ -275,22 +276,22 @@
             }
             text("After")
         }
-        val myComposer = compose {
+        val result = compose {
             composition()
         }
-        validate(myComposer.root) {
+        result.validate {
             composition()
         }
         includeA = false
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) {
+        result.expectChanges()
+        result.validate {
             composition()
         }
         includeA = true
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) {
+        result.expectChanges()
+        result.validate {
             composition()
         }
     }
@@ -316,14 +317,14 @@
             repeat(of = chars) { c -> textOf(c) }
         }
 
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             chars(chars)
             chars(chars)
             chars(chars)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             validatechars(chars)
             validatechars(chars)
             validatechars(chars)
@@ -331,9 +332,9 @@
 
         chars = listOf('a', 'b', 'x', 'c')
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             validatechars(chars)
             validatechars(chars)
             validatechars(chars)
@@ -343,13 +344,13 @@
     @Test
     fun testSimpleMemoize() {
         val points = listOf(Point(1, 2), Point(2, 3))
-        val myComposer = compose {
+        val result = compose {
             points(points)
         }
 
-        validate(myComposer.root) { points(points) }
+        result.validate { points(points) }
 
-        val changes = myComposer.recompose()
+        val changes = result.recompose()
         assertFalse(changes)
     }
 
@@ -362,12 +363,12 @@
             Point(6, 7)
         )
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             points(points)
         }
 
-        validate(myComposer.root) { points(points) }
+        result.validate { points(points) }
 
         points = listOf(
             Point(1, 2),
@@ -376,9 +377,9 @@
             Point(6, 7)
         )
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { points(points) }
+        result.validate { points(points) }
     }
 
     @Test
@@ -406,11 +407,11 @@
             rob_reports_to_alice,
             clark_reports_to_lois
         )
-        val myComposer = compose {
+        val result = compose {
             reportsReport(reports)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -418,7 +419,7 @@
             }
         }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
     }
 
     @Test
@@ -435,11 +436,11 @@
             }
         }
 
-        val myComposer = compose {
+        val result = compose {
             Two(41, 42)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             two(41, 42)
         }
     }
@@ -458,11 +459,11 @@
             }
         }
 
-        val myComposer = compose {
+        val result = compose {
             Three(41, 42, 43)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             three(41, 42, 43)
         }
     }
@@ -486,11 +487,11 @@
             }
         }
 
-        val myComposer = compose {
+        val result = compose {
             Four(41, 42, 43, 44)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             four(41, 42, 43, 44)
         }
     }
@@ -548,13 +549,13 @@
             test(showThree)
         }
 
-        val myComposer = compose(block = composition)
-        validate(myComposer.root, block = validation)
+        val result = compose(block = composition)
+        result.validate(validation)
 
         showThree = true
         recomposeTest()
-        myComposer.expectChanges()
-        validate(myComposer.root, block = validation)
+        result.expectChanges()
+        result.validate(validation)
     }
 
     @Test
@@ -573,20 +574,20 @@
 
         var value = 42
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             callOne(value)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             one(42)
         }
 
         value = 43
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             one(43)
         }
     }
@@ -607,25 +608,25 @@
 
         var value = 42
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             callOne(value)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             one(42)
         }
 
         value = 43
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             one(43)
         }
 
         changed!!()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
     }
 
     @Test
@@ -656,11 +657,11 @@
             jim_reports_to_sally,
             rob_reports_to_alice,
             clark_reports_to_lois, r)
-        val myComposer = compose {
+        val result = compose {
             reportsReport(reports)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -669,7 +670,7 @@
             }
         }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
         // Demote Perry
         r.from = "Perry"
@@ -678,9 +679,9 @@
         // Compose only the Lois report
         recomposeLois?.let { it() }
 
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -721,11 +722,11 @@
             jim_reports_to_sally,
             rob_reports_to_alice,
             clark_reports_to_lois, r)
-        val myComposer = compose {
+        val result = compose {
             reportsReport(reports)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -734,7 +735,7 @@
             }
         }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
         // Demote Perry
         r.from = "Perry"
@@ -746,9 +747,9 @@
         // Compose only the Lois report
         recomposeLois?.let { it() }
 
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -802,12 +803,12 @@
 
         var filter = all
         var changed = {}
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             reportsReport(reports, filter)
         }
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -818,9 +819,9 @@
 
         filter = notLois
         changed()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -829,9 +830,9 @@
 
         // Invalidate Lois which is now removed.
         recomposeLois()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) {
+        result.validate {
             linear {
                 reportsTo(jim_reports_to_sally)
                 reportsTo(rob_reports_to_alice)
@@ -862,16 +863,16 @@
             text("value = $value")
         }
 
-        val myComposer = compose {
+        val result = compose {
             test(1)
         }
 
-        validate(myComposer.root) { test(1) }
+        result.validate { test(1) }
 
         assertEquals(1, count)
 
         changed!!()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
         // Expect the previous instance to be remembered
         assertEquals(1, count)
@@ -898,23 +899,23 @@
 
         var value = 1
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             test(value)
         }
 
-        validate(myComposer.root) { test(1) }
+        result.validate { test(1) }
 
         value = 2
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { test(2) }
+        result.validate { test(2) }
 
         changed!!()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { test(2) }
+        result.validate { test(2) }
 
         assertEquals(2, count)
     }
@@ -942,24 +943,24 @@
         var p2 = 2
         var changed: (() -> Unit)? = null
 
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             test(p1, p2)
         }
 
-        validate(myComposer.root) { test(1, 2) }
+        result.validate { test(1, 2) }
 
         p1 = 2
         p2 = 3
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { test(2, 3) }
+        result.validate { test(2, 3) }
 
         changed!!()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { test(2, 3) }
+        result.validate { test(2, 3) }
 
         assertEquals(2, count)
     }
@@ -985,23 +986,23 @@
 
         var p3 = 3
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             test(1, 2, p3)
         }
 
-        validate(myComposer.root) { test(1, 2, 3) }
+        result.validate { test(1, 2, 3) }
 
         p3 = 4
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { test(1, 2, 4) }
+        result.validate { test(1, 2, 4) }
 
         changed!!()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { test(1, 2, 4) }
+        result.validate { test(1, 2, 4) }
 
         assertEquals(2, count)
     }
@@ -1029,24 +1030,24 @@
         var p4 = 4
         var changed: (() -> Unit)? = null
 
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             test(1, 2, p3, p4)
         }
 
-        validate(myComposer.root) { test(1, 2, 3, 4) }
+        result.validate { test(1, 2, 3, 4) }
 
         p3 = 4
         p4 = 5
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { test(1, 2, 4, 5) }
+        result.validate { test(1, 2, 4, 5) }
 
         changed!!()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { test(1, 2, 4, 5) }
+        result.validate { test(1, 2, 4, 5) }
 
         assertEquals(2, count)
     }
@@ -1072,23 +1073,23 @@
 
         var lastParameter = 5
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             test(1, 2, 3, 4, lastParameter)
         }
 
-        validate(myComposer.root) { test(1, 2, 3, 4, 5) }
+        result.validate { test(1, 2, 3, 4, 5) }
 
         lastParameter = 6
         changed!!()
 
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { test(1, 2, 3, 4, 6) }
+        result.validate { test(1, 2, 3, 4, 6) }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { test(1, 2, 3, 4, 6) }
+        result.validate { test(1, 2, 3, 4, 6) }
 
         assertEquals(2, count)
     }
@@ -1116,15 +1117,15 @@
             }
         }
 
-        val myComposer = compose { composition() }
+        val result = compose { composition() }
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
         for (i in 1..10) {
             values.add(i)
             changed!!()
-            myComposer.expectChanges()
-            validate(myComposer.root) { composition() }
+            result.expectChanges()
+            result.validate { composition() }
         }
     }
 
@@ -1164,14 +1165,14 @@
             }
         }
 
-        val myComposer = compose { composition() }
-        validate(myComposer.root) { composition() }
+        val result = compose { composition() }
+        result.validate { composition() }
 
         threeVisible = true
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
     }
 
     @Test
@@ -1191,16 +1192,16 @@
             }
         }
 
-        val myComposer = compose { composition() }
+        val result = compose { composition() }
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
         text = "Ending"
         myInvalidate?.let { it() }
 
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
     }
 
     @Test
@@ -1230,22 +1231,22 @@
             }
         }
 
-        val myComposer = compose { composition() }
+        val result = compose { composition() }
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
         text = "Ending"
         includeNested = false
         invalidate1()
         invalidate2()
 
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
     }
 
     @Test
@@ -1275,22 +1276,22 @@
             }
         }
 
-        val myComposer = compose { composition() }
+        val result = compose { composition() }
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
         text = "Ending"
         includeNested = false
         invalidate1?.invoke()
         invalidate2?.invoke()
 
-        myComposer.expectChanges()
+        result.expectChanges()
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
 
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
     }
 
     // b/132638679
@@ -1318,16 +1319,16 @@
             }
         }
 
-        val myComposer = compose { composition() }
+        val result = compose { composition() }
 
         texts = 4
         invalidateOuter?.invoke()
         invalidateInner?.invoke()
-        myComposer.expectChanges()
+        result.expectChanges()
 
         texts = 3
         invalidateOuter?.invoke()
-        myComposer.expectChanges()
+        result.expectChanges()
     }
 
     @Test
@@ -1357,17 +1358,17 @@
         }
 
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             composition()
         }
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
         assertEquals(1, lifecycleObject.count, "object should have been notified of an enter")
 
         changed!!()
-        myComposer.expectNoChanges()
-        validate(myComposer.root) { composition() }
+        result.expectNoChanges()
+        result.validate { composition() }
 
         assertEquals(1, lifecycleObject.count, "Object should have only been notified once")
     }
@@ -1408,17 +1409,17 @@
         }
 
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             composition()
         }
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
 
         assertEquals(1, lifecycleObject.count, "object should have been notified of an enter")
 
         changed!!()
-        myComposer.expectNoChanges()
-        validate(myComposer.root) { composition() }
+        result.expectNoChanges()
+        result.validate { composition() }
 
         assertEquals(1, lifecycleObject.count, "Object should have only been notified once")
     }
@@ -1460,24 +1461,24 @@
 
         var changed: (() -> Unit)? = null
         var value = true
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             composition(value)
         }
-        validate(myComposer.root) { composition(true) }
+        result.validate { composition(true) }
 
         assertEquals(1, lifecycleObject.count, "object should have been notified of an enter")
 
         changed!!()
-        myComposer.expectNoChanges()
-        validate(myComposer.root) { composition(true) }
+        result.expectNoChanges()
+        result.validate { composition(true) }
 
         assertEquals(1, lifecycleObject.count, "Object should have only been notified once")
 
         value = false
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) { composition(false) }
+        result.expectChanges()
+        result.validate { composition(false) }
 
         assertEquals(0, lifecycleObject.count, "Object should have been notified of a leave")
     }
@@ -1552,11 +1553,11 @@
         var b = false
         var c = false
         var changed: (() -> Unit)? = null
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             composition(a = a, b = b, c = c)
         }
-        validate(myComposer.root) {
+        result.validate {
             composition(
                 a = true,
                 b = false,
@@ -1573,8 +1574,8 @@
         expectedEnter = false
         expectedLeave = false
         changed!!()
-        myComposer.expectNoChanges()
-        validate(myComposer.root) {
+        result.expectNoChanges()
+        result.validate {
             composition(
                 a = true,
                 b = false,
@@ -1593,8 +1594,8 @@
         b = true
         c = false
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) {
+        result.expectChanges()
+        result.validate {
             composition(
                 a = false,
                 b = true,
@@ -1609,8 +1610,8 @@
         b = false
         c = true
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) {
+        result.expectChanges()
+        result.validate {
             composition(
                 a = false,
                 b = false,
@@ -1625,8 +1626,8 @@
         b = false
         c = false
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) {
+        result.expectChanges()
+        result.validate {
             composition(
                 a = true,
                 b = false,
@@ -1641,8 +1642,8 @@
         b = false
         c = false
         changed!!()
-        myComposer.expectChanges()
-        validate(myComposer.root) {
+        result.expectChanges()
+        result.validate {
             composition(
                 a = false,
                 b = false,
@@ -1696,25 +1697,25 @@
             }
         }
 
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             composition(obj = lifecycleObject)
         }
-        validate(myComposer.root) { composition() }
+        result.validate { composition() }
         assertEquals(1, lifecycleObject1.count, "first object should enter")
         assertEquals(0, lifecycleObject2.count, "second object should not have entered")
 
         lifecycleObject = lifecycleObject2
         changed()
-        myComposer.expectChanges()
-        validate(myComposer.root) { composition() }
+        result.expectChanges()
+        result.validate { composition() }
         assertEquals(0, lifecycleObject1.count, "first object should have left")
         assertEquals(1, lifecycleObject2.count, "second object should have entered")
 
         lifecycleObject = object {}
         changed()
-        myComposer.expectChanges()
-        validate(myComposer.root) { composition() }
+        result.expectChanges()
+        result.validate { composition() }
         assertEquals(0, lifecycleObject1.count, "first object should have left")
         assertEquals(0, lifecycleObject2.count, "second object should have left")
     }
@@ -1799,7 +1800,7 @@
         var value = true
         var changed: (() -> Unit)? = null
 
-        val myComposer = compose {
+        val result = compose {
             changed = invalidate
             composition(value)
         }
@@ -1811,7 +1812,7 @@
 
         value = false
         changed!!()
-        myComposer.expectChanges()
+        result.expectChanges()
 
         assertTrue(
             objects.mapNotNull { it as? Counted }.map { it.count == 0 }.all { it },
@@ -1847,16 +1848,16 @@
         @Composable
         fun MockComposeScope.test() {
             outerInvalidate = invalidate
-            outerKeys.add(composer.currentCompoundKeyHash)
+            outerKeys.add(currentComposer.currentCompoundKeyHash)
             Container {
                 innerInvalidate = invalidate
-                innerKeys.add(composer.currentCompoundKeyHash)
+                innerKeys.add(currentComposer.currentCompoundKeyHash)
             }
             // asserts that the key is correctly rolled back after start and end of Observe
-            assertEquals(outerKeys.last(), composer.currentCompoundKeyHash)
+            assertEquals(outerKeys.last(), currentComposer.currentCompoundKeyHash)
         }
 
-        val myComposer = compose {
+        val result = compose {
             test()
         }
 
@@ -1865,12 +1866,12 @@
 
         previousOuterKeysSize = outerKeys.size
         outerInvalidate()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
         assertNotEquals(previousOuterKeysSize, outerKeys.size)
 
         previousInnerKeysSize = innerKeys.size
         innerInvalidate()
-        myComposer.expectNoChanges()
+        result.expectNoChanges()
         assertNotEquals(previousInnerKeysSize, innerKeys.size)
 
         assertNotEquals(innerKeys[0], outerKeys[0])
@@ -1900,7 +1901,7 @@
             }
         }
 
-        val myComposer = compose {
+        val result = compose {
             test()
         }
 
@@ -1909,7 +1910,7 @@
         items[3] = 2
         invalidateComposition()
 
-        myComposer.expectChanges()
+        result.expectChanges()
     }
 
     @Test // b/154650546
@@ -1985,12 +1986,12 @@
             }
         }
 
-        val myComposition = compose {
+        val result = compose {
             test()
         }
 
         fun validate() {
-            validate(myComposition.root) {
+            result.validate {
                 test()
             }
         }
@@ -2006,7 +2007,7 @@
 
         invalidateComposition()
 
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
     }
 
@@ -2052,19 +2053,19 @@
             }
         }
 
-        val myComposition = compose {
+        val result = compose {
             test()
         }
 
-        validate(myComposition.root) {
+        result.validate {
             test()
         }
 
         items.add(2 to listOf(3, 4, 5, 6))
         invalidateComposition()
 
-        myComposition.expectChanges()
-        validate(myComposition.root) {
+        result.expectChanges()
+        result.validate {
             test()
         }
     }
@@ -2158,12 +2159,12 @@
             }
         }
 
-        val myComposition = compose {
+        val result = compose {
             test()
         }
 
         fun validate() {
-            validate(myComposition.root) {
+            result.validate {
                 test()
             }
         }
@@ -2171,29 +2172,29 @@
 
         includeEven = false
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         includeEven = true
         includeOdd = false
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         includeEven = false
         includeOdd = false
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         includeEven = true
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         includeOdd = true
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
     }
 
@@ -2212,11 +2213,6 @@
         }
 
         @Composable
-        fun MockComposeScope.wrapper(children: @Composable () -> Unit) {
-            children()
-        }
-
-        @Composable
         fun MockComposeScope.emitText(all: Boolean) {
             invalidates.add(invalidate)
             for (i in order) {
@@ -2288,12 +2284,12 @@
             }
         }
 
-        val myComposition = compose {
+        val result = compose {
             test()
         }
 
         fun validate() {
-            validate(myComposition.root) {
+            result.validate {
                 test()
             }
         }
@@ -2302,33 +2298,33 @@
         order = listOf(1, 2, 4, 3)
         includeEven = false
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         order = listOf(1, 4, 2, 3)
         includeEven = true
         includeOdd = false
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         order = listOf(3, 4, 2, 1)
         includeEven = false
         includeOdd = false
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         order = listOf(4, 3, 2, 1)
         includeEven = true
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
 
         order = listOf(1, 2, 3, 4)
         includeOdd = true
         invalidateComposition()
-        myComposition.expectChanges()
+        result.expectChanges()
         validate()
     }
 }
@@ -2345,14 +2341,36 @@
     }
 }
 
+private class CompositionResult(
+    val composer: Composer<*>,
+    val root: View
+) {
+    fun validate(block: MockViewValidator.() -> Unit) {
+        MockViewListValidator(root.children).validate(block)
+    }
+
+    fun expectNoChanges() {
+        val changes = composer.recompose() && composer.changeCount > 0
+        assertFalse(changes)
+    }
+
+    fun expectChanges() {
+        val changes = composer.recompose() && composer.changeCount > 0
+        assertTrue(changes, "Expected changes")
+        composer.applyChanges()
+        composer.slotTable.verifyWellFormed()
+    }
+
+    fun recompose(): Boolean = composer.recompose()
+}
+
 private fun compose(
     block: @Composable MockComposeScope.() -> Unit
-): MockViewComposer {
+): CompositionResult {
+    val root = View().apply { name = "root" }
     val composer = run {
-        val root = View().apply { name = "root" }
-
         val scope = CoroutineScope(Job())
-        val clock = object : CompositionFrameClock {
+        val clock = object : MonotonicFrameClock {
             override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R {
                 // The original version of this test used a mock Recomposer
                 // that never successfully scheduled a frame.
@@ -2363,28 +2381,23 @@
         val recomposer = Recomposer().apply {
             scope.launch { runRecomposeAndApplyChanges(clock) }
         }
-        MockViewComposer(root, recomposer)
+        Composer(
+            SlotTable(),
+            ViewApplier(root),
+            recomposer
+        )
     }
 
-    composer.compose {
-        block()
+    val mockScope = MockComposeScope()
+    composer.composeRoot {
+        invokeComposable(composer) {
+            mockScope.block()
+        }
     }
     composer.applyChanges()
     composer.slotTable.verifyWellFormed()
 
-    return composer
-}
-
-private fun MockViewComposer.expectNoChanges() {
-    val changes = recompose() && changeCount > 0
-    assertFalse(changes)
-}
-
-private fun MockViewComposer.expectChanges() {
-    val changes = recompose() && changeCount > 0
-    assertTrue(changes, "Expected changes")
-    applyChanges()
-    slotTable.verifyWellFormed()
+    return CompositionResult(composer, root)
 }
 
 // Contact test data
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt
index 15bb61d..5d24410 100644
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt
@@ -89,8 +89,4 @@
         val hasNext = next()
         assertEquals(true, hasNext)
     }
-}
-
-fun validate(root: View, block: MockViewValidator.() -> Unit) {
-    MockViewListValidator(root.children).validate(block)
-}
+}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewApplier.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewApplier.kt
new file mode 100644
index 0000000..7ded646
--- /dev/null
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewApplier.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.mock
+
+import androidx.compose.AbstractApplier
+import androidx.compose.Composable
+import androidx.compose.ComposeCompilerApi
+import androidx.compose.Composer
+import androidx.compose.ExperimentalComposeApi
+import androidx.compose.Stable
+import androidx.compose.currentComposer
+
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+@OptIn(ExperimentalComposeApi::class)
+class ViewApplier(root: View) : AbstractApplier<View>(root) {
+    override fun insert(index: Int, instance: View) {
+        current.addAt(index, instance)
+    }
+
+    override fun remove(index: Int, count: Int) {
+        current.removeAt(index, count)
+    }
+
+    override fun move(from: Int, to: Int, count: Int) {
+        current.moveAt(from, to, count)
+    }
+}
+
+@Stable
+class MockComposeScope
+
+// TODO(lmr): we should really remove this from our tests
+@Suppress("UNCHECKED_CAST")
+@OptIn(ComposeCompilerApi::class)
+@Composable
+fun <P1> MockComposeScope.memoize(
+    key: Int,
+    p1: P1,
+    block: @Composable (p1: P1) -> Unit
+) {
+    currentComposer.startGroup(key)
+    if (!currentComposer.changed(p1)) {
+        currentComposer.skipToGroupEnd()
+    } else {
+        val realFn = block as Function4<P1, Composer<*>, Int, Int, Unit>
+        realFn(p1, currentComposer, 0, 0)
+    }
+    currentComposer.endGroup()
+}
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewComposer.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewComposer.kt
deleted file mode 100644
index a5e5a30..0000000
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewComposer.kt
+++ /dev/null
@@ -1,115 +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.mock
-
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
-import androidx.compose.Composable
-import androidx.compose.ComposeCompilerApi
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
-import androidx.compose.ExperimentalComposeApi
-import androidx.compose.InternalComposeApi
-import androidx.compose.Recomposer
-import androidx.compose.SlotTable
-import androidx.compose.Stable
-import androidx.compose.currentComposer
-import androidx.compose.invokeComposable
-
-@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
-@OptIn(ExperimentalComposeApi::class)
-object ViewApplierAdapter :
-    ApplyAdapter<View> {
-    override fun View.start(instance: View) {}
-    override fun View.insertAt(index: Int, instance: View) = addAt(index, instance)
-    override fun View.removeAt(index: Int, count: Int) = removeAt(index, count)
-    override fun View.move(from: Int, to: Int, count: Int) = moveAt(from, to, count)
-    override fun View.end(instance: View, parent: View) {}
-}
-
-typealias Updater<T> = ComposerUpdater<View, T>
-
-@Stable
-interface MockComposeScope {
-    val composer: MockViewComposer
-}
-
-@OptIn(InternalComposeApi::class, ExperimentalComposeApi::class, ComposeCompilerApi::class)
-class MockViewComposer(
-    val root: View,
-    recomposer: Recomposer
-) : Composer<View>(SlotTable(), Applier(root, ViewApplierAdapter), recomposer), MockComposeScope {
-
-    override val composer: MockViewComposer get() = this
-
-    fun compose(composable: @Composable MockComposeScope.() -> Unit) {
-        composeRoot {
-            invokeComposable(this) {
-                val c = currentComposer as MockViewComposer
-                c.composable()
-            }
-        }
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    inline fun <V : View> emit(
-        key: Any,
-        ctor: () -> V,
-        update: Updater<V>.() -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor().also { emitNode(it) }
-        else useNode() as V
-        Updater(this, node).update()
-        endNode()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    inline fun <V : View> emit(
-        key: Any,
-        ctor: () -> V,
-        update: Updater<V>.() -> Unit,
-        children: () -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor().also { emitNode(it) }
-        else useNode() as V
-        Updater(this, node).update()
-        children()
-        endNode()
-    }
-}
-
-@Suppress("UNCHECKED_CAST")
-@OptIn(ComposeCompilerApi::class)
-@Composable
-fun <P1> MockComposeScope.memoize(
-    key: Int,
-    p1: P1,
-    block: @Composable (p1: P1) -> Unit
-) {
-    with(currentComposer as MockViewComposer) {
-        startGroup(key)
-        if (!changed(p1)) {
-            skipToGroupEnd()
-        } else {
-            val realFn = block as Function4<P1, Composer<*>, Int, Int, Unit>
-            realFn(p1, this, 0, 0)
-        }
-        endGroup()
-    }
-}
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt
index 7bf8106..85fcb49c 100644
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt
@@ -17,7 +17,7 @@
 package androidx.compose.mock
 
 import androidx.compose.Composable
-import androidx.compose.currentComposer
+import androidx.compose.emit
 import androidx.compose.key
 
 @Composable
@@ -34,28 +34,38 @@
 
 @Composable
 fun MockComposeScope.linear(block: @Composable MockComposeScope.() -> Unit) {
-    val c = currentComposer as MockViewComposer
-    View(name = "linear") {
-        c.block()
+    emit<View, ViewApplier>(
+        ctor = { View().also { it.name = "linear" } },
+        update = { }
+    ) {
+        block()
     }
 }
 
 @Composable
 fun MockComposeScope.text(value: String) {
-    View(name = "text", text = value)
+    emit<View, ViewApplier>(
+        ctor = { View().also { it.name = "text" } },
+        update = { set(value) { text = it } }
+    )
 }
 
 @Composable
 fun MockComposeScope.edit(value: String) {
-    View(name = "edit", value = value)
+    emit<View, ViewApplier>(
+        ctor = { View().also { it.name = "edit" } },
+        update = { set(value) { this.value = it } }
+    )
 }
 
 @Composable
 fun MockComposeScope.selectBox(selected: Boolean, block: @Composable MockComposeScope.() -> Unit) {
     if (selected) {
-        View(name = "box") {
-            block()
-        }
+        emit<View, ViewApplier>(
+            ctor = { View().also { it.name = "box" } },
+            update = { },
+            children = { block() }
+        )
     } else {
         block()
     }
diff --git a/core/core/api/1.5.0-alpha01.txt b/core/core/api/1.5.0-alpha01.txt
index f80f458..e6df9f3 100644
--- a/core/core/api/1.5.0-alpha01.txt
+++ b/core/core/api/1.5.0-alpha01.txt
@@ -1708,10 +1708,10 @@
   }
 
   public final class PatternsCompat {
-    field public static final java.util.regex.Pattern! DOMAIN_NAME;
-    field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
-    field public static final java.util.regex.Pattern! IP_ADDRESS;
-    field public static final java.util.regex.Pattern! WEB_URL;
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern WEB_URL;
   }
 
   public final class Pools {
diff --git a/core/core/api/api_lint.ignore b/core/core/api/api_lint.ignore
index 46772b6..b6158f8d 100644
--- a/core/core/api/api_lint.ignore
+++ b/core/core/api/api_lint.ignore
@@ -1085,14 +1085,6 @@
     Missing nullability on field `LTR` in class `class androidx.core.text.TextDirectionHeuristicsCompat`
 MissingNullability: androidx.core.text.TextDirectionHeuristicsCompat#RTL:
     Missing nullability on field `RTL` in class `class androidx.core.text.TextDirectionHeuristicsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#DOMAIN_NAME:
-    Missing nullability on field `DOMAIN_NAME` in class `class androidx.core.util.PatternsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#EMAIL_ADDRESS:
-    Missing nullability on field `EMAIL_ADDRESS` in class `class androidx.core.util.PatternsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#IP_ADDRESS:
-    Missing nullability on field `IP_ADDRESS` in class `class androidx.core.util.PatternsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#WEB_URL:
-    Missing nullability on field `WEB_URL` in class `class androidx.core.util.PatternsCompat`
 MissingNullability: androidx.core.view.AccessibilityDelegateCompat#dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent) parameter #0:
     Missing nullability on parameter `host` in method `dispatchPopulateAccessibilityEvent`
 MissingNullability: androidx.core.view.AccessibilityDelegateCompat#dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent) parameter #1:
@@ -2111,11 +2103,11 @@
     Provide an explicit copy constructor instead of implementing `clone()`
 
 
-OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #0:
+OptionalBuilderConstructorArgument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #0:
     Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter icon in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
-OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #1:
+OptionalBuilderConstructorArgument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #1:
     Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter title in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
-OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #2:
+OptionalBuilderConstructorArgument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #2:
     Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter intent in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
 
 
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index f80f458..e6df9f3 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -1708,10 +1708,10 @@
   }
 
   public final class PatternsCompat {
-    field public static final java.util.regex.Pattern! DOMAIN_NAME;
-    field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
-    field public static final java.util.regex.Pattern! IP_ADDRESS;
-    field public static final java.util.regex.Pattern! WEB_URL;
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern WEB_URL;
   }
 
   public final class Pools {
diff --git a/core/core/api/public_plus_experimental_1.5.0-alpha01.txt b/core/core/api/public_plus_experimental_1.5.0-alpha01.txt
index a9a4c2e..ce97204 100644
--- a/core/core/api/public_plus_experimental_1.5.0-alpha01.txt
+++ b/core/core/api/public_plus_experimental_1.5.0-alpha01.txt
@@ -1706,10 +1706,10 @@
   }
 
   public final class PatternsCompat {
-    field public static final java.util.regex.Pattern! DOMAIN_NAME;
-    field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
-    field public static final java.util.regex.Pattern! IP_ADDRESS;
-    field public static final java.util.regex.Pattern! WEB_URL;
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern WEB_URL;
   }
 
   public final class Pools {
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index a9a4c2e..ce97204 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -1706,10 +1706,10 @@
   }
 
   public final class PatternsCompat {
-    field public static final java.util.regex.Pattern! DOMAIN_NAME;
-    field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
-    field public static final java.util.regex.Pattern! IP_ADDRESS;
-    field public static final java.util.regex.Pattern! WEB_URL;
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern WEB_URL;
   }
 
   public final class Pools {
diff --git a/core/core/api/restricted_1.5.0-alpha01.txt b/core/core/api/restricted_1.5.0-alpha01.txt
index a3a2802..c1640ac 100644
--- a/core/core/api/restricted_1.5.0-alpha01.txt
+++ b/core/core/api/restricted_1.5.0-alpha01.txt
@@ -2051,12 +2051,12 @@
   }
 
   public final class PatternsCompat {
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_EMAIL_ADDRESS;
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_WEB_URL;
-    field public static final java.util.regex.Pattern! DOMAIN_NAME;
-    field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
-    field public static final java.util.regex.Pattern! IP_ADDRESS;
-    field public static final java.util.regex.Pattern! WEB_URL;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_EMAIL_ADDRESS;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_WEB_URL;
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern WEB_URL;
   }
 
   public final class Pools {
@@ -2878,7 +2878,7 @@
     method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
     method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
     method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat! CONSUMED;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat CONSUMED;
   }
 
   public static final class WindowInsetsCompat.Builder {
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index a3a2802..c1640ac 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -2051,12 +2051,12 @@
   }
 
   public final class PatternsCompat {
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_EMAIL_ADDRESS;
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_WEB_URL;
-    field public static final java.util.regex.Pattern! DOMAIN_NAME;
-    field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
-    field public static final java.util.regex.Pattern! IP_ADDRESS;
-    field public static final java.util.regex.Pattern! WEB_URL;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_EMAIL_ADDRESS;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_WEB_URL;
+    field public static final java.util.regex.Pattern DOMAIN_NAME;
+    field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+    field public static final java.util.regex.Pattern IP_ADDRESS;
+    field public static final java.util.regex.Pattern WEB_URL;
   }
 
   public final class Pools {
@@ -2878,7 +2878,7 @@
     method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
     method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
     method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat! CONSUMED;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat CONSUMED;
   }
 
   public static final class WindowInsetsCompat.Builder {
diff --git a/datastore/datastore-preferences/api/1.0.0-alpha01.txt b/datastore/datastore-preferences/api/1.0.0-alpha01.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/1.0.0-alpha01.txt
+++ b/datastore/datastore-preferences/api/1.0.0-alpha01.txt
@@ -19,7 +19,7 @@
     method public String getString(String key, String defaultValue);
     method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
     method public androidx.datastore.preferences.Preferences.Builder toBuilder();
-    field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+    field public static final androidx.datastore.preferences.Preferences.Companion Companion;
   }
 
   public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
 
   public final class SharedPreferencesMigration {
     method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
-    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
   }
 
   public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/current.txt b/datastore/datastore-preferences/api/current.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/current.txt
+++ b/datastore/datastore-preferences/api/current.txt
@@ -19,7 +19,7 @@
     method public String getString(String key, String defaultValue);
     method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
     method public androidx.datastore.preferences.Preferences.Builder toBuilder();
-    field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+    field public static final androidx.datastore.preferences.Preferences.Companion Companion;
   }
 
   public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
 
   public final class SharedPreferencesMigration {
     method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
-    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
   }
 
   public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt b/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -19,7 +19,7 @@
     method public String getString(String key, String defaultValue);
     method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
     method public androidx.datastore.preferences.Preferences.Builder toBuilder();
-    field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+    field public static final androidx.datastore.preferences.Preferences.Companion Companion;
   }
 
   public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
 
   public final class SharedPreferencesMigration {
     method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
-    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
   }
 
   public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/public_plus_experimental_current.txt b/datastore/datastore-preferences/api/public_plus_experimental_current.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/public_plus_experimental_current.txt
+++ b/datastore/datastore-preferences/api/public_plus_experimental_current.txt
@@ -19,7 +19,7 @@
     method public String getString(String key, String defaultValue);
     method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
     method public androidx.datastore.preferences.Preferences.Builder toBuilder();
-    field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+    field public static final androidx.datastore.preferences.Preferences.Companion Companion;
   }
 
   public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
 
   public final class SharedPreferencesMigration {
     method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
-    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
   }
 
   public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt b/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt
+++ b/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt
@@ -19,7 +19,7 @@
     method public String getString(String key, String defaultValue);
     method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
     method public androidx.datastore.preferences.Preferences.Builder toBuilder();
-    field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+    field public static final androidx.datastore.preferences.Preferences.Companion Companion;
   }
 
   public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
 
   public final class SharedPreferencesMigration {
     method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
-    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
   }
 
   public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/restricted_current.txt b/datastore/datastore-preferences/api/restricted_current.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/restricted_current.txt
+++ b/datastore/datastore-preferences/api/restricted_current.txt
@@ -19,7 +19,7 @@
     method public String getString(String key, String defaultValue);
     method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
     method public androidx.datastore.preferences.Preferences.Builder toBuilder();
-    field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+    field public static final androidx.datastore.preferences.Preferences.Companion Companion;
   }
 
   public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
 
   public final class SharedPreferencesMigration {
     method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
-    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+    field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
   }
 
   public static final class SharedPreferencesMigration.Companion {
diff --git a/development/build_log_simplifier.py b/development/build_log_simplifier.py
index b7f5cf2..4f838e4 100755
--- a/development/build_log_simplifier.py
+++ b/development/build_log_simplifier.py
@@ -74,10 +74,12 @@
       "A fine-grained performance profile is available: use the --scan option.",
       "* Get more help at https://help.gradle.org",
       "Use '--warning-mode all' to show the individual deprecation warnings.",
-      "See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings"
+      "See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings",
 
       "Note: Some input files use or override a deprecated API.",
-      "Note: Recompile with -Xlint:deprecation for details."
+      "Note: Recompile with -Xlint:deprecation for details.",
+      "Note: Some input files use unchecked or unsafe operations.",
+      "Note: Recompile with -Xlint:unchecked for details."
   }
   skipPrefixes = [
       "See the profiling report at:",
diff --git a/development/referenceDocs/stageComposeReferenceDocs.sh b/development/referenceDocs/stageComposeReferenceDocs.sh
index 95db2ae..d3c1831 100755
--- a/development/referenceDocs/stageComposeReferenceDocs.sh
+++ b/development/referenceDocs/stageComposeReferenceDocs.sh
@@ -93,7 +93,7 @@
 g4d -f androidx-ref-docs-stage && \
 cd third_party/devsite/android/en/reference && \
 g4 sync && \
-cp -r $newDir/reference/* . && \
+cp -r $(pwd)/* . && \
 /google/data/ro/projects/devsite/two/live/devsite2.par stage kotlin/androidx
 \`\`\`\n"
 
diff --git a/fragment/fragment-testing/api/1.3.0-alpha07.txt b/fragment/fragment-testing/api/1.3.0-alpha07.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/1.3.0-alpha07.txt
+++ b/fragment/fragment-testing/api/1.3.0-alpha07.txt
@@ -6,10 +6,12 @@
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
     method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
     method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
   public final class FragmentScenarioKt {
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
   }
 
diff --git a/fragment/fragment-testing/api/api_lint.ignore b/fragment/fragment-testing/api/api_lint.ignore
index 5f4e236..eb23956 100644
--- a/fragment/fragment-testing/api/api_lint.ignore
+++ b/fragment/fragment-testing/api/api_lint.ignore
@@ -1,9 +1,17 @@
 // Baseline format: 1.0
 MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
     Missing nullability on method `launchFragment` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory):
+    Missing nullability on method `launchFragment` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, kotlin.jvm.functions.Function0<? extends F>):
+    Missing nullability on method `launchFragment` return
 MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
     Missing nullability on method `launchFragment` return
 MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
     Missing nullability on method `launchFragmentInContainer` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory):
+    Missing nullability on method `launchFragmentInContainer` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, kotlin.jvm.functions.Function0<? extends F>):
+    Missing nullability on method `launchFragmentInContainer` return
 MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
     Missing nullability on method `launchFragmentInContainer` return
diff --git a/fragment/fragment-testing/api/current.txt b/fragment/fragment-testing/api/current.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/current.txt
+++ b/fragment/fragment-testing/api/current.txt
@@ -6,10 +6,12 @@
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
     method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
     method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
   public final class FragmentScenarioKt {
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
   }
 
diff --git a/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt b/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt
+++ b/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt
@@ -6,10 +6,12 @@
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
     method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
     method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
   public final class FragmentScenarioKt {
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
   }
 
diff --git a/fragment/fragment-testing/api/public_plus_experimental_current.txt b/fragment/fragment-testing/api/public_plus_experimental_current.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/public_plus_experimental_current.txt
+++ b/fragment/fragment-testing/api/public_plus_experimental_current.txt
@@ -6,10 +6,12 @@
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
     method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
     method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
   public final class FragmentScenarioKt {
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
   }
 
diff --git a/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt b/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt
+++ b/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt
@@ -6,10 +6,12 @@
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
     method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
     method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
   public final class FragmentScenarioKt {
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
   }
 
diff --git a/fragment/fragment-testing/api/restricted_current.txt b/fragment/fragment-testing/api/restricted_current.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/restricted_current.txt
+++ b/fragment/fragment-testing/api/restricted_current.txt
@@ -6,10 +6,12 @@
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
     method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+    method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
     method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
     method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
     method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
   public final class FragmentScenarioKt {
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
     method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+    method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
     method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
   }
 
diff --git a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt
index 0b27dd8..b11604f 100644
--- a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt
+++ b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt
@@ -106,8 +106,7 @@
 
     @Test
     fun fromCreatedToCreated() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
             moveToState(State.CREATED)
             onFragment { fragment ->
                 assertThat(fragment.lifecycle.currentState).isEqualTo(State.CREATED)
@@ -120,8 +119,7 @@
 
     @Test
     fun fromCreatedToStarted() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
             moveToState(State.STARTED)
             onFragment { fragment ->
                 assertThat(fragment.lifecycle.currentState).isEqualTo(State.STARTED)
@@ -133,8 +131,7 @@
 
     @Test
     fun fromCreatedToResumed() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
             moveToState(State.RESUMED)
             onFragment { fragment ->
                 assertThat(fragment.lifecycle.currentState).isEqualTo(State.RESUMED)
@@ -146,16 +143,14 @@
 
     @Test
     fun fromCreatedToDestroyed() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
             moveToState(State.DESTROYED)
         }
     }
 
     @Test
     fun fromStartedToCreated() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
             moveToState(State.CREATED)
             onFragment { fragment ->
                 assertThat(fragment.lifecycle.currentState).isEqualTo(State.CREATED)
@@ -168,8 +163,7 @@
 
     @Test
     fun fromStartedToStarted() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
             moveToState(State.STARTED)
             onFragment { fragment ->
                 assertThat(fragment.lifecycle.currentState).isEqualTo(State.STARTED)
@@ -181,8 +175,7 @@
 
     @Test
     fun fromStartedToResumed() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
             moveToState(State.RESUMED)
             onFragment { fragment ->
                 assertThat(fragment.lifecycle.currentState).isEqualTo(State.RESUMED)
@@ -194,8 +187,7 @@
 
     @Test
     fun fromStartedToDestroyed() {
-        with(launchFragment<SimpleDialogFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
             moveToState(State.DESTROYED)
         }
     }
@@ -211,12 +203,11 @@
     @Test
     fun recreateCreatedFragment() {
         var numOfInstantiation = 0
-        with(launchFragment {
+        with(launchFragment(initialState = State.CREATED) {
             ++numOfInstantiation
             SimpleDialogFragment()
         }) {
             assertThat(numOfInstantiation).isEqualTo(1)
-            moveToState(State.CREATED)
             recreate()
             assertThat(numOfInstantiation).isEqualTo(2)
             onFragment { fragment ->
@@ -231,12 +222,11 @@
     @Test
     fun recreateStartedFragment() {
         var numOfInstantiation = 0
-        with(launchFragment {
+        with(launchFragment(initialState = State.STARTED) {
             ++numOfInstantiation
             SimpleDialogFragment()
         }) {
             assertThat(numOfInstantiation).isEqualTo(1)
-            moveToState(State.STARTED)
             recreate()
             assertThat(numOfInstantiation).isEqualTo(2)
             onFragment { fragment ->
diff --git a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
index 80534a4..6d46dce 100644
--- a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
+++ b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
@@ -283,8 +283,7 @@
 
     @Test
     fun fromCreatedToCreated() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
             moveToState(State.CREATED)
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.CREATED)
@@ -295,8 +294,7 @@
 
     @Test
     fun fromCreatedToStarted() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
             moveToState(State.STARTED)
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.STARTED)
@@ -307,8 +305,7 @@
 
     @Test
     fun fromCreatedToResumed() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
             moveToState(State.RESUMED)
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.RESUMED)
@@ -319,16 +316,14 @@
 
     @Test
     fun fromCreatedToDestroyed() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
             moveToState(State.DESTROYED)
         }
     }
 
     @Test
     fun fromStartedToCreated() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
             moveToState(State.CREATED)
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.CREATED)
@@ -339,8 +334,7 @@
 
     @Test
     fun fromStartedToStarted() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
             moveToState(State.STARTED)
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.STARTED)
@@ -351,8 +345,7 @@
 
     @Test
     fun fromStartedToResumed() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
             moveToState(State.RESUMED)
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.RESUMED)
@@ -363,8 +356,7 @@
 
     @Test
     fun fromStartedToDestroyed() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
             moveToState(State.DESTROYED)
         }
     }
@@ -379,8 +371,7 @@
 
     @Test
     fun recreateCreatedFragment() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.CREATED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
             recreate()
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.CREATED)
@@ -391,8 +382,7 @@
 
     @Test
     fun recreateStartedFragment() {
-        with(launchFragmentInContainer<StateRecordingFragment>()) {
-            moveToState(State.STARTED)
+        with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
             recreate()
             onFragment { fragment ->
                 assertThat(fragment.state).isEqualTo(State.STARTED)
diff --git a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java
index 206f7cc..64ff90b 100644
--- a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java
+++ b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java
@@ -36,6 +36,7 @@
 import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentFactory;
 import androidx.fragment.testing.R;
+import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.Lifecycle.State;
 import androidx.lifecycle.ViewModel;
 import androidx.lifecycle.ViewModelProvider;
@@ -209,7 +210,31 @@
     public static <F extends Fragment> FragmentScenario<F> launch(
             @NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
             @StyleRes int themeResId, @Nullable FragmentFactory factory) {
-        return internalLaunch(fragmentClass, fragmentArgs, themeResId, factory,
+        return launch(fragmentClass, fragmentArgs, themeResId, Lifecycle.State.RESUMED,
+                factory);
+    }
+
+    /**
+     * Launches a Fragment with given arguments hosted by an empty {@link FragmentActivity} themed
+     * by {@code themeResId}, using the given {@link FragmentFactory} and waits for it to reach
+     * {@code initialState}.
+     * <p>
+     * This method cannot be called from the main thread.
+     *
+     * @param fragmentClass a fragment class to instantiate
+     * @param fragmentArgs a bundle to passed into fragment
+     * @param themeResId a style resource id to be set to the host activity's theme
+     * @param initialState The initial {@link Lifecycle.State}. This must be one of
+     * {@link State#CREATED CREATED}, {@link State#STARTED STARTED}, and
+     * {@link State#RESUMED RESUMED}.
+     * @param factory a fragment factory to use or null to use default factory
+     */
+    @NonNull
+    public static <F extends Fragment> FragmentScenario<F> launch(
+            @NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
+            @StyleRes int themeResId, @NonNull Lifecycle.State initialState,
+            @Nullable FragmentFactory factory) {
+        return internalLaunch(fragmentClass, fragmentArgs, themeResId, initialState, factory,
                 /*containerViewId=*/ 0);
     }
 
@@ -278,15 +303,41 @@
     public static <F extends Fragment> FragmentScenario<F> launchInContainer(
             @NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
             @StyleRes int themeResId, @Nullable FragmentFactory factory) {
+        return launchInContainer(fragmentClass, fragmentArgs, themeResId, Lifecycle.State.RESUMED,
+                factory);
+    }
+
+    /**
+     * Launches a Fragment in the Activity's root view container {@code android.R.id.content}, with
+     * given arguments hosted by an empty {@link FragmentActivity} themed by {@code themeResId},
+     * using the given {@link FragmentFactory} and waits for it to reach {@code initialState}.
+     * <p>
+     * This method cannot be called from the main thread.
+     *
+     * @param fragmentClass a fragment class to instantiate
+     * @param fragmentArgs a bundle to passed into fragment
+     * @param themeResId a style resource id to be set to the host activity's theme
+     * @param initialState The initial {@link Lifecycle.State}. This must be one of
+     * {@link State#CREATED CREATED}, {@link State#STARTED STARTED}, and
+     * {@link State#RESUMED RESUMED}.
+     * @param factory a fragment factory to use or null to use default factory
+     */
+    @NonNull
+    public static <F extends Fragment> FragmentScenario<F> launchInContainer(
+            @NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
+            @StyleRes int themeResId, @NonNull Lifecycle.State initialState,
+            @Nullable FragmentFactory factory) {
         return internalLaunch(
-                fragmentClass, fragmentArgs, themeResId, factory, android.R.id.content);
+                fragmentClass, fragmentArgs, themeResId, initialState, factory,
+                android.R.id.content);
     }
 
     @NonNull
     @SuppressLint("RestrictedApi")
     private static <F extends Fragment> FragmentScenario<F> internalLaunch(
             @NonNull final Class<F> fragmentClass, final @Nullable Bundle fragmentArgs,
-            @StyleRes int themeResId, @Nullable final FragmentFactory factory,
+            @StyleRes int themeResId, @NonNull Lifecycle.State initialState,
+            @Nullable final FragmentFactory factory,
             @IdRes final int containerViewId) {
         Intent startActivityIntent =
                 Intent.makeMainActivity(
@@ -310,6 +361,7 @@
             activity.getSupportFragmentManager()
                     .beginTransaction()
                     .add(containerViewId, fragment, FRAGMENT_TAG)
+                    .setMaxLifecycle(fragment, initialState)
                     .commitNow();
         });
         return scenario;
diff --git a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
index 4766100..0854cfa 100644
--- a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
+++ b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
@@ -22,74 +22,122 @@
 import androidx.fragment.app.FragmentActivity
 import androidx.fragment.app.FragmentFactory
 import androidx.fragment.testing.R
+import androidx.lifecycle.Lifecycle
+
+@Deprecated("Superseded by launchFragment that takes an initialState",
+    level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragment(
+    fragmentArgs: Bundle? = null,
+    @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    factory: FragmentFactory? = null
+) = launchFragment<F>(fragmentArgs, themeResId, Lifecycle.State.RESUMED, factory)
+
+@Deprecated("Superseded by launchFragment that takes an initialState",
+    level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragment(
+    fragmentArgs: Bundle? = null,
+    @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    crossinline instantiate: () -> F
+) = launchFragment(fragmentArgs, themeResId) {
+    instantiate()
+}
+
+@Deprecated("Superseded by launchFragmentInContainer that takes an initialState",
+    level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragmentInContainer(
+    fragmentArgs: Bundle? = null,
+    @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    factory: FragmentFactory? = null
+) = launchFragmentInContainer<F>(fragmentArgs, themeResId, Lifecycle.State.RESUMED, factory)
+
+@Deprecated("Superseded by launchFragmentInContainer that takes an initialState",
+    level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragmentInContainer(
+    fragmentArgs: Bundle? = null,
+    @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    crossinline instantiate: () -> F
+) = launchFragmentInContainer(fragmentArgs, themeResId) {
+    instantiate()
+}
 
 /**
  * Launches a Fragment with given arguments hosted by an empty [FragmentActivity] using
- * given [FragmentFactory] and waits for it to reach a resumed state.
+ * given [FragmentFactory] and waits for it to reach [initialState].
  *
  * This method cannot be called from the main thread.
  *
  * @param fragmentArgs a bundle to passed into fragment
  * @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
  * @param factory a fragment factory to use or null to use default factory
  */
 inline fun <reified F : Fragment> launchFragment(
     fragmentArgs: Bundle? = null,
     @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    initialState: Lifecycle.State = Lifecycle.State.RESUMED,
     factory: FragmentFactory? = null
-) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, factory)
+) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, initialState, factory)
 
 /**
  * Launches a Fragment with given arguments hosted by an empty [FragmentActivity] using
- * [instantiate] to create the Fragment and waits for it to reach a resumed state.
+ * [instantiate] to create the Fragment and waits for it to reach [initialState].
  *
  * This method cannot be called from the main thread.
  *
  * @param fragmentArgs a bundle to passed into fragment
  * @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
  * @param instantiate method which will be used to instantiate the Fragment.
  */
 inline fun <reified F : Fragment> launchFragment(
     fragmentArgs: Bundle? = null,
     @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    initialState: Lifecycle.State = Lifecycle.State.RESUMED,
     crossinline instantiate: () -> F
-) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, object : FragmentFactory() {
-    override fun instantiate(
-        classLoader: ClassLoader,
-        className: String
-    ) = when (className) {
-        F::class.java.name -> instantiate()
-        else -> super.instantiate(classLoader, className)
-    }
-})
+) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, initialState,
+    object : FragmentFactory() {
+        override fun instantiate(
+            classLoader: ClassLoader,
+            className: String
+        ) = when (className) {
+            F::class.java.name -> instantiate()
+            else -> super.instantiate(classLoader, className)
+        }
+    })
 
 /**
  * Launches a Fragment in the Activity's root view container `android.R.id.content`, with
- * given arguments hosted by an empty [FragmentActivity] and waits for it to reach a
- * resumed state.
+ * given arguments hosted by an empty [FragmentActivity] and waits for it to reach [initialState].
  *
  * This method cannot be called from the main thread.
  *
  * @param fragmentArgs a bundle to passed into fragment
  * @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
  * @param factory a fragment factory to use or null to use default factory
  */
 inline fun <reified F : Fragment> launchFragmentInContainer(
     fragmentArgs: Bundle? = null,
     @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    initialState: Lifecycle.State = Lifecycle.State.RESUMED,
     factory: FragmentFactory? = null
-) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId, factory)
+) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId, initialState,
+    factory)
 
 /**
  * Launches a Fragment in the Activity's root view container `android.R.id.content`, with
  * given arguments hosted by an empty [FragmentActivity] using
- * [instantiate] to create the Fragment and waits for it to reach a
- * resumed state.
+ * [instantiate] to create the Fragment and waits for it to reach [initialState].
  *
  * This method cannot be called from the main thread.
  *
  * @param fragmentArgs a bundle to passed into fragment
  * @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
  * @param instantiate method which will be used to instantiate the Fragment. This is a
  * simplification of the [FragmentFactory] interface for cases where only a single class
  * needs a custom constructor called.
@@ -97,8 +145,9 @@
 inline fun <reified F : Fragment> launchFragmentInContainer(
     fragmentArgs: Bundle? = null,
     @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+    initialState: Lifecycle.State = Lifecycle.State.RESUMED,
     crossinline instantiate: () -> F
-) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId,
+) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId, initialState,
     object : FragmentFactory() {
         override fun instantiate(
             classLoader: ClassLoader,
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
index 11f56ca..cc758d9 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
@@ -144,6 +144,92 @@
     }
 
     @Test
+    fun testClearResultListenerInCallback() {
+        with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+            val fm = withActivity {
+                setContentView(R.layout.simple_container)
+                supportFragmentManager
+            }
+
+            val fragment1 = ClearResultFragment()
+
+            // set a result while no listener is available so it is stored in the fragment manager
+            fm.setFragmentResult("requestKey", Bundle())
+
+            // adding the fragment is going to execute and clear its listener.
+            withActivity {
+                fm.beginTransaction()
+                    .add(R.id.fragmentContainer, fragment1)
+                    .commitNow()
+            }
+
+            // lets set another listener with the same key as the original
+            fm.setFragmentResultListener("requestKey", fragment1,
+                FragmentResultListener { _, _ -> })
+
+            // do a replace to force the lifecycle back below STARTED
+            fm.beginTransaction()
+                .replace(R.id.fragmentContainer, StrictFragment())
+                .addToBackStack(null)
+                .commit()
+            executePendingTransactions()
+
+            // store the result in the fragment manager since no listener is available
+            fm.setFragmentResult("requestKey", Bundle())
+
+            // pop the back stack to execute the new listener
+            withActivity {
+                fm.popBackStackImmediate()
+            }
+
+            assertWithMessage("the first listener should only be executed once")
+                .that(fragment1.callbackCount).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun testResetResultListener() {
+        with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+            val fm = withActivity {
+                setContentView(R.layout.simple_container)
+                supportFragmentManager
+            }
+
+            var firstListenerFired = false
+            var secondListenerFired = false
+
+            val fragment1 = StrictFragment()
+
+            // set a listener
+            fm.setFragmentResultListener("requestKey", fragment1,
+                FragmentResultListener { _, _ ->
+                    firstListenerFired = true
+                })
+
+            // lets set another listener before the first is fired
+            fm.setFragmentResultListener("requestKey", fragment1,
+                FragmentResultListener { _, _ ->
+                    secondListenerFired = true
+                })
+
+            // set a result while no listener is available so it is stored in the fragment manager
+            fm.setFragmentResult("requestKey", Bundle())
+
+            // adding the fragment is going to execute the listener's callback
+            withActivity {
+                fm.beginTransaction()
+                    .add(R.id.fragmentContainer, fragment1)
+                    .commitNow()
+            }
+
+            assertWithMessage("the first listener should never be executed")
+                .that(firstListenerFired).isFalse()
+            assertWithMessage("the second listener should have be executed")
+                .that(secondListenerFired).isTrue()
+        }
+    }
+
+    @Test
     fun testSetResultWhileResumed() {
         with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
             val fm = withActivity {
@@ -293,6 +379,20 @@
     }
 }
 
+class ClearResultFragment : StrictFragment() {
+    var callbackCount = 0
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        parentFragmentManager.setFragmentResultListener("requestKey", this,
+            FragmentResultListener { _, _ ->
+                callbackCount++
+                parentFragmentManager.clearFragmentResultListener("requestKey")
+            })
+    }
+}
+
 class ParentResultFragment : StrictFragment() {
     var actualResult: String? = null
 
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index 39592ff..18dd954a 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -210,11 +210,14 @@
     private static class LifecycleAwareResultListener implements FragmentResultListener {
         private final Lifecycle mLifecycle;
         private final FragmentResultListener mListener;
+        private final LifecycleEventObserver mObserver;
 
         LifecycleAwareResultListener(@NonNull Lifecycle lifecycle,
-                @NonNull FragmentResultListener listener) {
+                @NonNull FragmentResultListener listener,
+                @NonNull LifecycleEventObserver observer) {
             mLifecycle = lifecycle;
             mListener = listener;
+            mObserver = observer;
         }
 
         public boolean isAtLeast(Lifecycle.State state) {
@@ -225,6 +228,10 @@
         public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle result) {
             mListener.onFragmentResult(requestKey, result);
         }
+
+        public void removeObserver() {
+            mLifecycle.removeObserver(mObserver);
+        }
     }
 
     /**
@@ -871,12 +878,19 @@
             }
         };
         lifecycle.addObserver(observer);
-        mResultListeners.put(requestKey, new LifecycleAwareResultListener(lifecycle, listener));
+        LifecycleAwareResultListener storedListener = mResultListeners.put(requestKey,
+                new LifecycleAwareResultListener(lifecycle, listener, observer));
+        if (storedListener != null) {
+            storedListener.removeObserver();
+        }
     }
 
     @Override
     public final void clearFragmentResultListener(@NonNull String requestKey) {
-        mResultListeners.remove(requestKey);
+        LifecycleAwareResultListener listener = mResultListeners.remove(requestKey);
+        if (listener != null) {
+            listener.removeObserver();
+        }
     }
 
     /**
diff --git a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
index 58b8625..711bb2c 100644
--- a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
+++ b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
@@ -62,7 +62,7 @@
 
             @Override
             @NonNull
-            public MyViewModel create(@NonNull SavedStateHandle arg0) {
+            public MyViewModel create(SavedStateHandle arg0) {
                 return new MyViewModel();
             }
         }
@@ -112,7 +112,7 @@
 
             @Override
             @NonNull
-            public MyViewModel create(@NonNull SavedStateHandle arg0) {
+            public MyViewModel create(SavedStateHandle arg0) {
                 return new MyViewModel(arg0);
             }
         }
@@ -180,7 +180,7 @@
 
             @Override
             @NonNull
-            public MyViewModel create(@NonNull SavedStateHandle arg0) {
+            public MyViewModel create(SavedStateHandle arg0) {
                 return new MyViewModel(s.get(), f.get(), arg0, l.get());
             }
         }
@@ -246,7 +246,7 @@
 
             @Override
             @NonNull
-            public MyViewModel create(@NonNull SavedStateHandle arg0) {
+            public MyViewModel create(SavedStateHandle arg0) {
                 return new MyViewModel(s.get(), f, arg0);
             }
         }
@@ -322,7 +322,7 @@
 
             @Override
             @NonNull
-            public MyViewModel create(@NonNull SavedStateHandle arg0) {
+            public MyViewModel create(SavedStateHandle arg0) {
                 return new MyViewModel(s.get(), l, arg0);
             }
         }
@@ -421,7 +421,7 @@
 
             @Override
             @NonNull
-            public Outer.InnerViewModel create(@NonNull SavedStateHandle arg0) {
+            public Outer.InnerViewModel create(SavedStateHandle arg0) {
                 return new Outer.InnerViewModel();
             }
         }
diff --git a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt
index c5360b4..371e533 100644
--- a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt
+++ b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt
@@ -87,7 +87,7 @@
 
             @Override
             @NonNull
-            public MyWorker create(@NonNull Context arg0, @NonNull WorkerParameters arg1) {
+            public MyWorker create(Context arg0, WorkerParameters arg1) {
                 return new MyWorker(arg0, arg1, s.get(), f.get(), l.get());
             }
         }
diff --git a/jetifier/jetifier/migration.config b/jetifier/jetifier/migration.config
index a39738b..0e7bb80 100644
--- a/jetifier/jetifier/migration.config
+++ b/jetifier/jetifier/migration.config
@@ -302,13 +302,85 @@
   "slRules": [
     {
       "from": "androidx/core/view/inputmethod/(.*)",
-      "to": "android/support/v13/view/inputmethod/{0}"
+      "to": "ignore"
     },
     {
       "from": "androidx/core/content/ContextCompat(.*)",
       "to": "ignore"
     },
     {
+      "from": "androidx/core/app/Person(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/math/MathUtils(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/net/(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/provider/(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/text/util/(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/text/(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/JobIntentService(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/accessibilityservice/AccessibilityServiceInfoCompat(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/ActivityCompat(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/ActivityManagerCompat(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/ActivityOptionsCompat(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/ActivityRecreator(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/AlarmManagerCompat(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/AppComponentFactory(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/AppLaunchChecker(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/AppOpsManagerCompat(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/app/CoreComponentFactory(.*)",
+      "to": "ignore"
+    },
+    {
+      "from": "androidx/core/os/(.*)",
+      "to": "ignore"
+    },
+    {
       "from": "androidx/viewpager2/(.*)",
       "to": "ignore"
     },
@@ -3779,18 +3851,9 @@
       "android/support/multidex/MultiDexApplication": "androidx/multidex/MultiDexApplication",
       "android/support/multidex/MultiDexExtractor": "androidx/multidex/MultiDexExtractor",
       "android/support/multidex/ZipUtil": "androidx/multidex/ZipUtil",
-      "android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat": "androidx/core/accessibilityservice/AccessibilityServiceInfoCompat",
-      "android/support/v4/app/ActivityCompat": "androidx/core/app/ActivityCompat",
-      "android/support/v4/app/ActivityManagerCompat": "androidx/core/app/ActivityManagerCompat",
-      "android/support/v4/app/ActivityOptionsCompat": "androidx/core/app/ActivityOptionsCompat",
-      "android/support/v4/app/AlarmManagerCompat": "androidx/core/app/AlarmManagerCompat",
-      "android/support/v4/app/AppComponentFactory": "androidx/core/app/AppComponentFactory",
-      "android/support/v4/app/AppLaunchChecker": "androidx/core/app/AppLaunchChecker",
-      "android/support/v4/app/AppOpsManagerCompat": "androidx/core/app/AppOpsManagerCompat",
       "android/support/v4/app/BackStackRecord": "androidx/fragment/app/BackStackRecord",
       "android/support/v4/app/BackStackState": "androidx/fragment/app/BackStackState",
       "android/support/v4/app/BundleCompat": "androidx/core/app/BundleCompat",
-      "android/support/v4/app/CoreComponentFactory": "androidx/core/app/CoreComponentFactory",
       "android/support/v4/app/DialogFragment": "androidx/fragment/app/DialogFragment",
       "android/support/v4/app/Fragment": "androidx/fragment/app/Fragment",
       "android/support/v4/app/FragmentActivity": "androidx/fragment/app/FragmentActivity",
@@ -3811,7 +3874,6 @@
       "android/support/v4/app/FragmentTransitionImpl": "androidx/fragment/app/FragmentTransitionImpl",
       "android/support/v4/app/FrameMetricsAggregator": "androidx/core/app/FrameMetricsAggregator",
       "android/support/v4/app/INotificationSideChannel": "androidx/core/app/INotificationSideChannel",
-      "android/support/v4/app/JobIntentService": "androidx/core/app/JobIntentService",
       "android/support/v4/app/ListFragment": "androidx/fragment/app/ListFragment",
       "android/support/v4/app/NavUtils": "androidx/core/app/NavUtils",
       "android/support/v4/app/NotificationBuilderWithBuilderAccessor": "androidx/core/app/NotificationBuilderWithBuilderAccessor",
@@ -3822,7 +3884,6 @@
       "android/support/v4/app/NotificationCompatSideChannelService": "androidx/core/app/NotificationCompatSideChannelService",
       "android/support/v4/app/NotificationManagerCompat": "androidx/core/app/NotificationManagerCompat",
       "android/support/v4/app/OneShotPreDrawListener": "androidx/fragment/app/OneShotPreDrawListener",
-      "android/support/v4/app/Person": "androidx/core/app/Person",
       "android/support/v4/app/RemoteInput": "androidx/core/app/RemoteInput",
       "android/support/v4/app/ServiceCompat": "androidx/core/app/ServiceCompat",
       "android/support/v4/app/ShareCompat": "androidx/core/app/ShareCompat",
@@ -3881,39 +3942,6 @@
       "android/support/v4/internal/view/SupportMenu": "androidx/core/internal/view/SupportMenu",
       "android/support/v4/internal/view/SupportMenuItem": "androidx/core/internal/view/SupportMenuItem",
       "android/support/v4/internal/view/SupportSubMenu": "androidx/core/internal/view/SupportSubMenu",
-      "android/support/v4/math/MathUtils": "androidx/core/math/MathUtils",
-      "android/support/v4/net/ConnectivityManagerCompat": "androidx/core/net/ConnectivityManagerCompat",
-      "android/support/v4/net/DatagramSocketWrapper": "androidx/core/net/DatagramSocketWrapper",
-      "android/support/v4/net/TrafficStatsCompat": "androidx/core/net/TrafficStatsCompat",
-      "android/support/v4/os/BuildCompat": "androidx/core/os/BuildCompat",
-      "android/support/v4/os/CancellationSignal": "androidx/core/os/CancellationSignal",
-      "android/support/v4/os/ConfigurationCompat": "androidx/core/os/ConfigurationCompat",
-      "android/support/v4/os/EnvironmentCompat": "androidx/core/os/EnvironmentCompat",
-      "android/support/v4/os/HandlerCompat": "androidx/core/os/HandlerCompat",
-      "android/support/v4/os/IResultReceiver": "androidx/core/os/IResultReceiver",
-      "android/support/v4/os/LocaleHelper": "androidx/core/os/LocaleHelper",
-      "android/support/v4/os/LocaleListCompat": "androidx/core/os/LocaleListCompat",
-      "android/support/v4/os/LocaleListHelper": "androidx/core/os/LocaleListHelper",
-      "android/support/v4/os/LocaleListInterface": "androidx/core/os/LocaleListInterface",
-      "android/support/v4/os/OperationCanceledException": "androidx/core/os/OperationCanceledException",
-      "android/support/v4/os/ParcelCompat": "androidx/core/os/ParcelCompat",
-      "android/support/v4/os/ParcelableCompat": "androidx/core/os/ParcelableCompat",
-      "android/support/v4/os/ParcelableCompatCreatorCallbacks": "androidx/core/os/ParcelableCompatCreatorCallbacks",
-      "android/support/v4/os/ResultReceiver": "androidx/core/os/ResultReceiver",
-      "android/support/v4/os/TraceCompat": "androidx/core/os/TraceCompat",
-      "android/support/v4/os/UserManagerCompat": "androidx/core/os/UserManagerCompat",
-      "android/support/v4/provider/FontRequest": "androidx/core/provider/FontRequest",
-      "android/support/v4/provider/FontsContractCompat": "androidx/core/provider/FontsContractCompat",
-      "android/support/v4/provider/SelfDestructiveThread": "androidx/core/provider/SelfDestructiveThread",
-      "android/support/v4/text/BidiFormatter": "androidx/core/text/BidiFormatter",
-      "android/support/v4/text/HtmlCompat": "androidx/core/text/HtmlCompat",
-      "android/support/v4/text/ICUCompat": "androidx/core/text/ICUCompat",
-      "android/support/v4/text/PrecomputedTextCompat": "androidx/core/text/PrecomputedTextCompat",
-      "android/support/v4/text/TextDirectionHeuristicCompat": "androidx/core/text/TextDirectionHeuristicCompat",
-      "android/support/v4/text/TextDirectionHeuristicsCompat": "androidx/core/text/TextDirectionHeuristicsCompat",
-      "android/support/v4/text/TextUtilsCompat": "androidx/core/text/TextUtilsCompat",
-      "android/support/v4/text/util/FindAddress": "androidx/core/text/util/FindAddress",
-      "android/support/v4/text/util/LinkifyCompat": "androidx/core/text/util/LinkifyCompat",
       "android/support/v4/util/AtomicFile": "androidx/core/util/AtomicFile",
       "android/support/v4/util/Consumer": "androidx/core/util/Consumer",
       "android/support/v4/util/DebugUtils": "androidx/core/util/DebugUtils",
@@ -4154,9 +4182,6 @@
       "android/support/v7/widget/helper/ItemTouchUIUtil": "androidx/recyclerview/widget/ItemTouchUIUtil",
       "android/support/v7/widget/helper/ItemTouchUIUtilImpl": "androidx/recyclerview/widget/ItemTouchUIUtilImpl",
       "android/support/v7/widget/util/SortedListAdapterCallback": "androidx/recyclerview/widget/SortedListAdapterCallback",
-      "android/support/v13/view/inputmethod/EditorInfoCompat": "androidx/core/view/inputmethod/EditorInfoCompat",
-      "android/support/v13/view/inputmethod/InputConnectionCompat": "androidx/core/view/inputmethod/InputConnectionCompat",
-      "android/support/v13/view/inputmethod/InputContentInfoCompat": "androidx/core/view/inputmethod/InputContentInfoCompat",
       "android/viewbinding/ViewBinding": "androidx/viewbinding/ViewBinding"
     }
   },
diff --git a/leanback/leanback/api/1.1.0-alpha04.txt b/leanback/leanback/api/1.1.0-alpha04.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/1.1.0-alpha04.txt
+++ b/leanback/leanback/api/1.1.0-alpha04.txt
@@ -1530,7 +1530,7 @@
     field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
     field public static final int VIEW_TYPE_INFO = 1; // 0x1
     field public static final int VIEW_TYPE_MAIN = 0; // 0x0
-    field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+    field public int viewType;
   }
 
   public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/current.txt b/leanback/leanback/api/current.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/current.txt
+++ b/leanback/leanback/api/current.txt
@@ -1530,7 +1530,7 @@
     field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
     field public static final int VIEW_TYPE_INFO = 1; // 0x1
     field public static final int VIEW_TYPE_MAIN = 0; // 0x0
-    field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+    field public int viewType;
   }
 
   public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt b/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt
+++ b/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt
@@ -1530,7 +1530,7 @@
     field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
     field public static final int VIEW_TYPE_INFO = 1; // 0x1
     field public static final int VIEW_TYPE_MAIN = 0; // 0x0
-    field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+    field public int viewType;
   }
 
   public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/public_plus_experimental_current.txt b/leanback/leanback/api/public_plus_experimental_current.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/public_plus_experimental_current.txt
+++ b/leanback/leanback/api/public_plus_experimental_current.txt
@@ -1530,7 +1530,7 @@
     field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
     field public static final int VIEW_TYPE_INFO = 1; // 0x1
     field public static final int VIEW_TYPE_MAIN = 0; // 0x0
-    field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+    field public int viewType;
   }
 
   public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/restricted_1.1.0-alpha04.txt b/leanback/leanback/api/restricted_1.1.0-alpha04.txt
index 0606e63..dc22fe8 100644
--- a/leanback/leanback/api/restricted_1.1.0-alpha04.txt
+++ b/leanback/leanback/api/restricted_1.1.0-alpha04.txt
@@ -1740,7 +1740,7 @@
     field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
     field public static final int VIEW_TYPE_INFO = 1; // 0x1
     field public static final int VIEW_TYPE_MAIN = 0; // 0x0
-    field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+    field public int viewType;
   }
 
   public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/restricted_current.txt b/leanback/leanback/api/restricted_current.txt
index 0606e63..dc22fe8 100644
--- a/leanback/leanback/api/restricted_current.txt
+++ b/leanback/leanback/api/restricted_current.txt
@@ -1740,7 +1740,7 @@
     field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
     field public static final int VIEW_TYPE_INFO = 1; // 0x1
     field public static final int VIEW_TYPE_MAIN = 0; // 0x0
-    field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+    field public int viewType;
   }
 
   public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt b/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt
@@ -9,6 +9,11 @@
   }
 
   public enum Lifecycle.Event {
+    method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+    method public androidx.lifecycle.Lifecycle.State getTargetState();
+    method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
     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;
diff --git a/lifecycle/lifecycle-common/api/current.txt b/lifecycle/lifecycle-common/api/current.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/current.txt
+++ b/lifecycle/lifecycle-common/api/current.txt
@@ -9,6 +9,11 @@
   }
 
   public enum Lifecycle.Event {
+    method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+    method public androidx.lifecycle.Lifecycle.State getTargetState();
+    method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
     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;
diff --git a/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt b/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt
@@ -9,6 +9,11 @@
   }
 
   public enum Lifecycle.Event {
+    method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+    method public androidx.lifecycle.Lifecycle.State getTargetState();
+    method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
     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;
diff --git a/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
@@ -9,6 +9,11 @@
   }
 
   public enum Lifecycle.Event {
+    method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+    method public androidx.lifecycle.Lifecycle.State getTargetState();
+    method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
     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;
diff --git a/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt b/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt
index 0a6849f..0e3bc8a 100644
--- a/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt
@@ -16,6 +16,11 @@
   }
 
   public enum Lifecycle.Event {
+    method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+    method public androidx.lifecycle.Lifecycle.State getTargetState();
+    method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
     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;
diff --git a/lifecycle/lifecycle-common/api/restricted_current.txt b/lifecycle/lifecycle-common/api/restricted_current.txt
index 0a6849f..0e3bc8a 100644
--- a/lifecycle/lifecycle-common/api/restricted_current.txt
+++ b/lifecycle/lifecycle-common/api/restricted_current.txt
@@ -16,6 +16,11 @@
   }
 
   public enum Lifecycle.Event {
+    method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+    method public androidx.lifecycle.Lifecycle.State getTargetState();
+    method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+    method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
     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;
diff --git a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java
index 78e9f92..a57e43d 100644
--- a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java
+++ b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java
@@ -18,6 +18,7 @@
 
 import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 
 import java.util.concurrent.atomic.AtomicReference;
@@ -153,7 +154,123 @@
         /**
          * An {@link Event Event} constant that can be used to match all events.
          */
-        ON_ANY
+        ON_ANY;
+
+        /**
+         * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+         * leaving the specified {@link Lifecycle.State} to a lower state, or {@code null}
+         * if there is no valid event that can move down from the given state.
+         *
+         * @param state the higher state that the returned event will transition down from
+         * @return the event moving down the lifecycle phases from state
+         */
+        @Nullable
+        public static Event downFrom(@NonNull State state) {
+            switch (state) {
+                case CREATED:
+                    return ON_DESTROY;
+                case STARTED:
+                    return ON_STOP;
+                case RESUMED:
+                    return ON_PAUSE;
+                default:
+                    return null;
+            }
+        }
+
+        /**
+         * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+         * entering the specified {@link Lifecycle.State} from a higher state, or {@code null}
+         * if there is no valid event that can move down to the given state.
+         *
+         * @param state the lower state that the returned event will transition down to
+         * @return the event moving down the lifecycle phases to state
+         */
+        @Nullable
+        public static Event downTo(@NonNull State state) {
+            switch (state) {
+                case DESTROYED:
+                    return ON_DESTROY;
+                case CREATED:
+                    return ON_STOP;
+                case STARTED:
+                    return ON_PAUSE;
+                default:
+                    return null;
+            }
+        }
+
+        /**
+         * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+         * leaving the specified {@link Lifecycle.State} to a higher state, or {@code null}
+         * if there is no valid event that can move up from the given state.
+         *
+         * @param state the lower state that the returned event will transition up from
+         * @return the event moving up the lifecycle phases from state
+         */
+        @Nullable
+        public static Event upFrom(@NonNull State state) {
+            switch (state) {
+                case INITIALIZED:
+                    return ON_CREATE;
+                case CREATED:
+                    return ON_START;
+                case STARTED:
+                    return ON_RESUME;
+                default:
+                    return null;
+            }
+        }
+
+        /**
+         * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+         * entering the specified {@link Lifecycle.State} from a lower state, or {@code null}
+         * if there is no valid event that can move up to the given state.
+         *
+         * @param state the higher state that the returned event will transition up to
+         * @return the event moving up the lifecycle phases to state
+         */
+        @Nullable
+        public static Event upTo(@NonNull State state) {
+            switch (state) {
+                case CREATED:
+                    return ON_CREATE;
+                case STARTED:
+                    return ON_START;
+                case RESUMED:
+                    return ON_RESUME;
+                default:
+                    return null;
+            }
+        }
+
+        /**
+         * Returns the new {@link Lifecycle.State} of a {@link Lifecycle} that just reported
+         * this {@link Lifecycle.Event}.
+         *
+         * Throws {@link IllegalArgumentException} if called on {@link #ON_ANY}, as it is a special
+         * value used by {@link OnLifecycleEvent} and not a real lifecycle event.
+         *
+         * @return the state that will result from this event
+         */
+        @NonNull
+        public State getTargetState() {
+            switch (this) {
+                case ON_CREATE:
+                case ON_STOP:
+                    return State.CREATED;
+                case ON_START:
+                case ON_PAUSE:
+                    return State.STARTED;
+                case ON_RESUME:
+                    return State.RESUMED;
+                case ON_DESTROY:
+                    return State.DESTROYED;
+                case ON_ANY:
+                    break;
+            }
+            throw new IllegalArgumentException(this + " has no target state");
+        }
     }
 
     /**
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
index eee40a8..578bd71 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
@@ -16,41 +16,55 @@
 
 package androidx.lifecycle
 
+import androidx.arch.core.executor.ArchTaskExecutor
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CompletableDeferred
 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.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
 @RunWith(AndroidJUnit4::class)
 class FlowAsLiveDataIntegrationTest {
+
+    @Before
+    fun clearArchExecutors() {
+        // make sure we don't receive a modified delegate. b/159212029
+        ArchTaskExecutor.getInstance().setDelegate(null)
+    }
+
     @Test
     @SmallTest
     fun startStopImmediately() {
         runBlocking {
-            val mediator = withContext(Dispatchers.Main) {
+            val stopChannelFlow = CompletableDeferred<Unit>()
+            val (mediator, liveData) = withContext(Dispatchers.Main) {
                 val mediator = MediatorLiveData<Int>()
                 val liveData = channelFlow {
                     send(1)
-                    delay(30000) // prevent block from ending
+                    // prevent block from ending
+                    stopChannelFlow.await()
                 }.asLiveData()
                 mediator.addSource(liveData) {
                     mediator.removeSource(liveData)
                     mediator.value = -it
                 }
-                mediator
+                mediator to liveData
             }
             val read = mediator.asFlow().first()
-            Truth.assertThat(read).isEqualTo(-1)
+            assertThat(read).isEqualTo(-1)
+            assertThat(liveData.hasObservers()).isFalse()
+            // make sure this test doesn't leak a running coroutine
+            stopChannelFlow.complete(Unit)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt b/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt
@@ -7,6 +7,10 @@
     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 LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+    ctor public LifecycleDestroyedException();
+  }
+
   public final class LifecycleKt {
     method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
   }
@@ -29,5 +33,16 @@
     method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
   }
 
+  public final class WithLifecycleStateKt {
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+  }
+
 }
 
diff --git a/lifecycle/lifecycle-runtime-ktx/api/current.txt b/lifecycle/lifecycle-runtime-ktx/api/current.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/current.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/current.txt
@@ -7,6 +7,10 @@
     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 LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+    ctor public LifecycleDestroyedException();
+  }
+
   public final class LifecycleKt {
     method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
   }
@@ -29,5 +33,16 @@
     method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
   }
 
+  public final class WithLifecycleStateKt {
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+  }
+
 }
 
diff --git a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt
@@ -7,6 +7,10 @@
     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 LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+    ctor public LifecycleDestroyedException();
+  }
+
   public final class LifecycleKt {
     method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
   }
@@ -29,5 +33,16 @@
     method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
   }
 
+  public final class WithLifecycleStateKt {
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+  }
+
 }
 
diff --git a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt
@@ -7,6 +7,10 @@
     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 LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+    ctor public LifecycleDestroyedException();
+  }
+
   public final class LifecycleKt {
     method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
   }
@@ -29,5 +33,16 @@
     method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
   }
 
+  public final class WithLifecycleStateKt {
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+  }
+
 }
 
diff --git a/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt b/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt
index 60b6383..3d7a81d 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt
@@ -7,6 +7,10 @@
     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 LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+    ctor public LifecycleDestroyedException();
+  }
+
   public final class LifecycleKt {
     method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
   }
@@ -29,5 +33,18 @@
     method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
   }
 
+  public final class WithLifecycleStateKt {
+    method @kotlin.PublishedApi internal static suspend <R> Object? suspendWithStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, boolean dispatchNeeded, kotlinx.coroutines.CoroutineDispatcher lifecycleDispatcher, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method @kotlin.PublishedApi internal static suspend inline <R> Object? withStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+  }
+
 }
 
diff --git a/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt b/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt
index 60b6383..3d7a81d 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt
@@ -7,6 +7,10 @@
     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 LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+    ctor public LifecycleDestroyedException();
+  }
+
   public final class LifecycleKt {
     method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
   }
@@ -29,5 +33,18 @@
     method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
   }
 
+  public final class WithLifecycleStateKt {
+    method @kotlin.PublishedApi internal static suspend <R> Object? suspendWithStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, boolean dispatchNeeded, kotlinx.coroutines.CoroutineDispatcher lifecycleDispatcher, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+    method @kotlin.PublishedApi internal static suspend inline <R> Object? withStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+  }
+
 }
 
diff --git a/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/WithLifecycleStateTest.kt b/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/WithLifecycleStateTest.kt
new file mode 100644
index 0000000..fadcc5d
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/WithLifecycleStateTest.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.filters.SmallTest
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.yield
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+@SmallTest
+class WithLifecycleStateTest {
+    @Test
+    fun testInitialResumed() = runBlocking(Dispatchers.Main) {
+        val owner = FakeLifecycleOwner(Lifecycle.State.RESUMED)
+
+        val expected = "initial value"
+        var toRead = expected
+        launch { toRead = "value set by launch" }
+        val readByWithStarted = owner.withStarted { toRead }
+        assertEquals(expected, readByWithStarted)
+    }
+
+    @Test
+    fun testBlockRunsWithLifecycleStateChange() = runBlocking(Dispatchers.Main) {
+        val owner = FakeLifecycleOwner()
+
+        val initial = "initial value"
+        val afterSetState = "value set after setState"
+        var toRead = initial
+        launch {
+            owner.setState(Lifecycle.State.RESUMED)
+            toRead = afterSetState
+        }
+        val readByWithStarted = owner.withStarted { toRead }
+        val readAfterResumed = toRead
+        assertEquals(initial, readByWithStarted)
+        assertEquals(afterSetState, readAfterResumed)
+    }
+
+    @Test
+    fun testBlockCancelledWhenInitiallyDestroyed() = runBlocking(Dispatchers.Main) {
+        val owner = FakeLifecycleOwner(Lifecycle.State.DESTROYED)
+
+        val result = runCatching {
+            owner.withStarted {}
+        }
+
+        assertTrue("withStarted threw LifecycleDestroyedException",
+            result.exceptionOrNull() is LifecycleDestroyedException)
+    }
+
+    @Test
+    fun testBlockCancelledWhenDestroyedWhileSuspended() = runBlocking(Dispatchers.Main) {
+        val owner = FakeLifecycleOwner(Lifecycle.State.CREATED)
+
+        var launched = false
+        val resultTask = async {
+            launched = true
+            runCatching { owner.withStarted {} }
+        }
+        yield()
+
+        assertTrue("test ran to first suspension after successfully launching", launched)
+        assertTrue("withStarted is still active", resultTask.isActive)
+
+        owner.setState(Lifecycle.State.DESTROYED)
+
+        assertTrue("result threw LifecycleDestroyedException",
+            resultTask.await().exceptionOrNull() is LifecycleDestroyedException)
+    }
+}
diff --git a/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/WithLifecycleState.kt b/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/WithLifecycleState.kt
new file mode 100644
index 0000000..ac741f5
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/WithLifecycleState.kt
@@ -0,0 +1,205 @@
+/*
+ * 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 kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlin.coroutines.coroutineContext
+import kotlin.coroutines.resumeWithException
+
+/**
+ * A [CancellationException] that indicates that the [Lifecycle] associated with an operation
+ * reached the [Lifecycle.State.DESTROYED] state before the operation could complete.
+ */
+class LifecycleDestroyedException : CancellationException()
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [state] and
+ * resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withStateAtLeast(
+    state: Lifecycle.State,
+    crossinline block: () -> R
+): R {
+    require(state >= Lifecycle.State.CREATED) {
+        "target state must be CREATED or greater, found $state"
+    }
+
+    return withStateAtLeastUnchecked(state, block)
+}
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [Lifecycle.State.CREATED]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withCreated(
+    crossinline block: () -> R
+): R = withStateAtLeastUnchecked(
+    state = Lifecycle.State.CREATED,
+    block = block
+)
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [Lifecycle.State.STARTED]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withStarted(
+    crossinline block: () -> R
+): R = withStateAtLeastUnchecked(
+    state = Lifecycle.State.STARTED,
+    block = block
+)
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [Lifecycle.State.RESUMED]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withResumed(
+    crossinline block: () -> R
+): R = withStateAtLeastUnchecked(
+    state = Lifecycle.State.RESUMED,
+    block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least [state]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withStateAtLeast(
+    state: Lifecycle.State,
+    crossinline block: () -> R
+): R = lifecycle.withStateAtLeast(
+    state = state,
+    block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least
+ * [Lifecycle.State.CREATED] and resume with the result.
+ * Throws the [CancellationException] [LifecycleDestroyedException] if the lifecycle has reached
+ * [Lifecycle.State.DESTROYED] by the time of the call or before [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withCreated(
+    crossinline block: () -> R
+): R = lifecycle.withStateAtLeastUnchecked(
+    state = Lifecycle.State.CREATED,
+    block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least
+ * [Lifecycle.State.STARTED] and resume with the result.
+ * Throws the [CancellationException] [LifecycleDestroyedException] if the lifecycle has reached
+ * [Lifecycle.State.DESTROYED] by the time of the call or before [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withStarted(
+    crossinline block: () -> R
+): R = lifecycle.withStateAtLeastUnchecked(
+    state = Lifecycle.State.STARTED,
+    block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least
+ * [Lifecycle.State.RESUMED] and resume with the result.
+ * Throws the [CancellationException] [LifecycleDestroyedException] if the lifecycle has reached
+ * [Lifecycle.State.DESTROYED] by the time of the call or before [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withResumed(
+    crossinline block: () -> R
+): R = lifecycle.withStateAtLeastUnchecked(
+    state = Lifecycle.State.RESUMED,
+    block = block
+)
+
+/**
+ * The inlined check for whether dispatch is necessary to perform [Lifecycle.withStateAtLeast]
+ * operations that does not bounds-check [state]. Used internally when we know the target state
+ * is already in bounds. Runs [block] inline without allocating if possible.
+ */
+@PublishedApi
+internal suspend inline fun <R> Lifecycle.withStateAtLeastUnchecked(
+    state: Lifecycle.State,
+    crossinline block: () -> R
+): R {
+    // Fast path: if our lifecycle dispatcher doesn't require dispatch we can check
+    // the current lifecycle state and decide if we can run synchronously
+    val lifecycleDispatcher = Dispatchers.Main.immediate
+    val dispatchNeeded = lifecycleDispatcher.isDispatchNeeded(coroutineContext)
+    if (!dispatchNeeded) {
+        if (currentState == Lifecycle.State.DESTROYED) throw LifecycleDestroyedException()
+        if (currentState >= state) return block()
+    }
+
+    return suspendWithStateAtLeastUnchecked(state, dispatchNeeded, lifecycleDispatcher) {
+        block()
+    }
+}
+
+/**
+ * The "slow" code path for [Lifecycle.withStateAtLeast] operations that requires allocating
+ * and suspending, factored into a non-inlined function to avoid inflating code size at call sites
+ * or exposing too many implementation details as inlined code.
+ */
+@PublishedApi
+internal suspend fun <R> Lifecycle.suspendWithStateAtLeastUnchecked(
+    state: Lifecycle.State,
+    dispatchNeeded: Boolean,
+    lifecycleDispatcher: CoroutineDispatcher,
+    block: () -> R
+): R = suspendCancellableCoroutine { co ->
+    val observer = object : LifecycleEventObserver {
+        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
+            if (event == Lifecycle.Event.upTo(state)) {
+                removeObserver(this)
+                co.resumeWith(runCatching(block))
+            } else if (event == Lifecycle.Event.ON_DESTROY) {
+                removeObserver(this)
+                co.resumeWithException(LifecycleDestroyedException())
+            }
+        }
+    }
+
+    if (dispatchNeeded) {
+        lifecycleDispatcher.dispatch(
+            EmptyCoroutineContext,
+            Runnable { addObserver(observer) }
+        )
+    } else addObserver(observer)
+
+    co.invokeOnCancellation {
+        if (lifecycleDispatcher.isDispatchNeeded(EmptyCoroutineContext)) {
+            lifecycleDispatcher.dispatch(
+                EmptyCoroutineContext,
+                Runnable { removeObserver(observer) }
+            )
+        } else removeObserver(observer)
+    }
+}
diff --git a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java
index 43a92e5..6a29743 100644
--- a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java
+++ b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java
@@ -16,17 +16,8 @@
 
 package androidx.lifecycle;
 
-import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
-import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-import static androidx.lifecycle.Lifecycle.Event.ON_START;
-import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
-import static androidx.lifecycle.Lifecycle.State.CREATED;
 import static androidx.lifecycle.Lifecycle.State.DESTROYED;
 import static androidx.lifecycle.Lifecycle.State.INITIALIZED;
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-import static androidx.lifecycle.Lifecycle.State.STARTED;
 
 import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
@@ -127,8 +118,7 @@
      * @param event The event that was received
      */
     public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
-        State next = getStateAfter(event);
-        moveToState(next);
+        moveToState(event.getTargetState());
     }
 
     private void moveToState(State next) {
@@ -185,7 +175,11 @@
         while ((statefulObserver.mState.compareTo(targetState) < 0
                 && mObserverMap.contains(observer))) {
             pushParentState(statefulObserver.mState);
-            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
+            final Event event = Event.upFrom(statefulObserver.mState);
+            if (event == null) {
+                throw new IllegalStateException("no event up from " + statefulObserver.mState);
+            }
+            statefulObserver.dispatchEvent(lifecycleOwner, event);
             popParentState();
             // mState / subling may have been changed recalculate
             targetState = calculateTargetState(observer);
@@ -239,55 +233,6 @@
         return mState;
     }
 
-    static State getStateAfter(Event event) {
-        switch (event) {
-            case ON_CREATE:
-            case ON_STOP:
-                return CREATED;
-            case ON_START:
-            case ON_PAUSE:
-                return STARTED;
-            case ON_RESUME:
-                return RESUMED;
-            case ON_DESTROY:
-                return DESTROYED;
-            case ON_ANY:
-                break;
-        }
-        throw new IllegalArgumentException("Unexpected event value " + event);
-    }
-
-    private static Event downEvent(State state) {
-        switch (state) {
-            case INITIALIZED:
-                throw new IllegalArgumentException();
-            case CREATED:
-                return ON_DESTROY;
-            case STARTED:
-                return ON_STOP;
-            case RESUMED:
-                return ON_PAUSE;
-            case DESTROYED:
-                throw new IllegalArgumentException();
-        }
-        throw new IllegalArgumentException("Unexpected state value " + state);
-    }
-
-    private static Event upEvent(State state) {
-        switch (state) {
-            case INITIALIZED:
-            case DESTROYED:
-                return ON_CREATE;
-            case CREATED:
-                return ON_START;
-            case STARTED:
-                return ON_RESUME;
-            case RESUMED:
-                throw new IllegalArgumentException();
-        }
-        throw new IllegalArgumentException("Unexpected state value " + state);
-    }
-
     private void forwardPass(LifecycleOwner lifecycleOwner) {
         Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                 mObserverMap.iteratorWithAdditions();
@@ -297,7 +242,11 @@
             while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                     && mObserverMap.contains(entry.getKey()))) {
                 pushParentState(observer.mState);
-                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
+                final Event event = Event.upFrom(observer.mState);
+                if (event == null) {
+                    throw new IllegalStateException("no event up from " + observer.mState);
+                }
+                observer.dispatchEvent(lifecycleOwner, event);
                 popParentState();
             }
         }
@@ -311,8 +260,11 @@
             ObserverWithState observer = entry.getValue();
             while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                     && mObserverMap.contains(entry.getKey()))) {
-                Event event = downEvent(observer.mState);
-                pushParentState(getStateAfter(event));
+                Event event = Event.downFrom(observer.mState);
+                if (event == null) {
+                    throw new IllegalStateException("no event down from " + observer.mState);
+                }
+                pushParentState(event.getTargetState());
                 observer.dispatchEvent(lifecycleOwner, event);
                 popParentState();
             }
@@ -356,7 +308,7 @@
         }
 
         void dispatchEvent(LifecycleOwner owner, Event event) {
-            State newState = getStateAfter(event);
+            State newState = event.getTargetState();
             mState = min(mState, newState);
             mLifecycleObserver.onStateChanged(owner, event);
             mState = newState;
diff --git a/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java b/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java
index 414fb28..6f1f317 100644
--- a/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java
+++ b/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java
@@ -280,10 +280,6 @@
         final TestObserver observer2 = mock(TestObserver.class);
         mRegistry.addObserver(observer2);
         verify(observer2, never()).onCreate();
-        reset(observer1);
-        dispatchEvent(ON_CREATE);
-        verify(observer1).onCreate();
-        verify(observer2).onCreate();
     }
 
     @Test
@@ -605,7 +601,7 @@
     }
 
     private void dispatchEvent(Lifecycle.Event event) {
-        when(mLifecycle.getCurrentState()).thenReturn(LifecycleRegistry.getStateAfter(event));
+        when(mLifecycle.getCurrentState()).thenReturn(event.getTargetState());
         mRegistry.handleLifecycleEvent(event);
     }
 
diff --git a/media2/common/api/api_lint.ignore b/media2/common/api/api_lint.ignore
index d2bb9aa..d3d06d5 100644
--- a/media2/common/api/api_lint.ignore
+++ b/media2/common/api/api_lint.ignore
@@ -13,9 +13,5 @@
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putText(String,CharSequence)
 
 
-GenericException: androidx.media2.common.SessionPlayer#close():
-    Methods must not throw generic exceptions (`java.lang.Exception`)
-
-
 IntentName: androidx.media2.common.MediaMetadata#METADATA_KEY_EXTRAS:
     Intent extra constant name must be EXTRA_FOO: METADATA_KEY_EXTRAS
diff --git a/media2/player/api/api_lint.ignore b/media2/player/api/api_lint.ignore
index f6d216c..bc67ff2 100644
--- a/media2/player/api/api_lint.ignore
+++ b/media2/player/api/api_lint.ignore
@@ -7,9 +7,5 @@
     Must avoid boxed primitives (`java.lang.Float`)
 
 
-GenericException: androidx.media2.player.MediaPlayer#close():
-    Methods must not throw generic exceptions (`java.lang.Exception`)
-
-
 MissingNullability: androidx.media2.player.TimedMetaData#getMetaData():
     Missing nullability on method `getMetaData` return
diff --git a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
similarity index 94%
rename from media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
rename to media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
index 1ab31ca..5a31569 100644
--- a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
+++ b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
@@ -68,8 +68,8 @@
  * Tests whether {@link MediaBrowserCompat} works well with {@link MediaLibraryService}.
  */
 @LargeTest
-public class MediaBrowserCompatTestWithMediaLibraryService extends
-        MediaBrowserCompatTestWithMediaSessionService {
+public class MediaBrowserCompatWithMediaLibraryServiceTest extends
+        MediaBrowserCompatWithMediaSessionServiceTest {
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -86,7 +86,7 @@
     }
 
     @Test
-    public void testGetRoot() throws InterruptedException {
+    public void getRoot() throws InterruptedException {
         // The MockMediaLibraryService gives MediaBrowserConstants.ROOT_ID as root ID, and
         // MediaBrowserConstants.ROOT_EXTRAS as extras.
         sHandler.postAndSync(new Runnable() {
@@ -105,7 +105,7 @@
     }
 
     @Test
-    public void testGetItem() throws InterruptedException {
+    public void getItem() throws InterruptedException {
         final String mediaId = MEDIA_ID_GET_ITEM;
 
         connectAndWait();
@@ -122,7 +122,7 @@
     }
 
     @Test
-    public void testGetItem_nullResult() throws InterruptedException {
+    public void getItem_nullResult() throws InterruptedException {
         final String mediaId = "random_media_id";
 
         connectAndWait();
@@ -143,7 +143,7 @@
     }
 
     @Test
-    public void testGetChildren() throws InterruptedException {
+    public void getChildren() throws InterruptedException {
         final String testParentId = PARENT_ID;
 
         connectAndWait();
@@ -173,7 +173,7 @@
     }
 
     @Test
-    public void testGetChildren_withLongList() throws InterruptedException {
+    public void getChildren_withLongList() throws InterruptedException {
         final String testParentId = PARENT_ID_LONG_LIST;
 
         connectAndWait();
@@ -203,7 +203,7 @@
     }
 
     @Test
-    public void testGetChildren_withPagination() throws InterruptedException {
+    public void getChildren_withPagination() throws InterruptedException {
         final String testParentId = PARENT_ID;
         final int page = 4;
         final int pageSize = 10;
@@ -246,7 +246,7 @@
     }
 
     @Test
-    public void testGetChildren_emptyResult() throws InterruptedException {
+    public void getChildren_emptyResult() throws InterruptedException {
         final String testParentId = PARENT_ID_NO_CHILDREN;
 
         connectAndWait();
@@ -264,7 +264,7 @@
     }
 
     @Test
-    public void testGetChildren_nullResult() throws InterruptedException {
+    public void getChildren_nullResult() throws InterruptedException {
         final String testParentId = PARENT_ID_ERROR;
 
         connectAndWait();
@@ -286,7 +286,7 @@
     }
 
     @Test
-    public void testSearch() throws InterruptedException {
+    public void search() throws InterruptedException {
         final String testQuery = SEARCH_QUERY;
         final int page = 4;
         final int pageSize = 10;
@@ -325,7 +325,7 @@
     }
 
     @Test
-    public void testSearch_withLongList() throws InterruptedException {
+    public void search_withLongList() throws InterruptedException {
         final String testQuery = SEARCH_QUERY_LONG_LIST;
         final int page = 0;
         final int pageSize = Integer.MAX_VALUE;
@@ -355,7 +355,7 @@
     }
 
     @Test
-    public void testSearch_emptyResult() throws InterruptedException {
+    public void search_emptyResult() throws InterruptedException {
         final String testQuery = SEARCH_QUERY_EMPTY_RESULT;
         final Bundle testExtras = new Bundle();
         testExtras.putString(testQuery, testQuery);
@@ -377,7 +377,7 @@
     }
 
     @Test
-    public void testSearch_error() throws InterruptedException {
+    public void search_error() throws InterruptedException {
         final String testQuery = SEARCH_QUERY_ERROR;
         final Bundle testExtras = new Bundle();
         testExtras.putString(testQuery, testQuery);
@@ -403,7 +403,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribe() throws InterruptedException {
+    public void subscribe() throws InterruptedException {
 //        final String testParentId = "testSubscribeId";
 //        final List<MediaItem> testList = TestUtils.createMediaItems(3);
 //
@@ -448,7 +448,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribe_withExtras() throws InterruptedException {
+    public void subscribe_withExtras() throws InterruptedException {
 //        final String testParentId = "testSubscribe_withExtras";
 //        final Bundle testExtras = new Bundle();
 //        testExtras.putString(testParentId, testParentId);
@@ -499,7 +499,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribe_withPagination() throws InterruptedException {
+    public void subscribe_withPagination() throws InterruptedException {
 //        final String testParentId = "testSubscribe_pagination_ID";
 //        final List<MediaItem> testList = TestUtils.createMediaItems(3);
 //        final int testPage = 2;
@@ -565,7 +565,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribeAndUnsubscribe() throws InterruptedException {
+    public void subscribeAndUnsubscribe() throws InterruptedException {
 //        final String testParentId = "testUnsubscribe";
 //        final Bundle testExtras = new Bundle();
 //        testExtras.putString(testParentId, testParentId);
@@ -605,7 +605,7 @@
 
     @Ignore("TODO: Split this test to here and MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testNotifyChildrenChanged() throws InterruptedException {
+    public void notifyChildrenChanged() throws InterruptedException {
 //        final String testSubscribedParentId = "testNotifyChildrenChanged";
 //        final String testUnsubscribedParentId = "testNotifyChildrenChanged22";
 //        final Bundle testExtras = new Bundle();
@@ -658,7 +658,7 @@
 
     // TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
     @Test
-    public void testCustomAction() throws InterruptedException {
+    public void customAction() throws InterruptedException {
         final Bundle testArgs = new Bundle();
         testArgs.putString("args_key", "args_value");
 
@@ -678,7 +678,7 @@
 
     // TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
     @Test
-    public void testCustomAction_rejected() throws InterruptedException {
+    public void customAction_rejected() throws InterruptedException {
         // This action will not be allowed by the library session.
         final String testAction = "random_custom_action";
 
diff --git a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
similarity index 93%
rename from media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
rename to media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
index 41c0cea..07fd59f 100644
--- a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
+++ b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
@@ -41,7 +41,7 @@
  * Tests whether {@link MediaBrowserCompat} works well with {@link MediaSessionService}.
  */
 @LargeTest
-public class MediaBrowserCompatTestWithMediaSessionService extends MediaSessionTestBase {
+public class MediaBrowserCompatWithMediaSessionServiceTest extends MediaSessionTestBase {
     MediaBrowserCompat mBrowserCompat;
     TestConnectionCallback mConnectionCallback;
 
@@ -79,21 +79,21 @@
     }
 
     @Test
-    public void testConnect() throws InterruptedException {
+    public void connect() throws InterruptedException {
         connectAndWait();
         assertNotEquals(0, mConnectionCallback.mFailedLatch.getCount());
     }
 
     @Ignore
     @Test
-    public void testConnect_rejected() throws InterruptedException {
+    public void connect_rejected() throws InterruptedException {
         // TODO: Connect the browser to the session service whose onConnect() returns null.
         assertTrue(mConnectionCallback.mFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         assertNotEquals(0, mConnectionCallback.mConnectedLatch.getCount());
     }
 
     @Test
-    public void testGetSessionToken() throws Exception {
+    public void getSessionToken() throws Exception {
         connectAndWait();
         MediaControllerCompat controller = new MediaControllerCompat(mContext,
                 mBrowserCompat.getSessionToken());
diff --git a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
similarity index 95%
rename from media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
rename to media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
index e5d1fd7..178411f 100644
--- a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
+++ b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
@@ -58,7 +58,7 @@
  */
 @RunWith(AndroidJUnit4.class)
 @LargeTest
-public class MediaControllerCompatCallbackTestWithMediaSession extends MediaSessionTestBase {
+public class MediaControllerCompatCallbackWithMediaSessionTest extends MediaSessionTestBase {
     private static final String TAG = "MCCCallbackTestWithMS2";
 
     private static final long TIMEOUT_MS = 1000L;
@@ -82,7 +82,7 @@
     }
 
     @Test
-    public void testRepeatModeChange() throws Exception {
+    public void repeatModeChange() throws Exception {
         final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
 
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -97,7 +97,7 @@
     }
 
     @Test
-    public void testShuffleModeChange() throws Exception {
+    public void shuffleModeChange() throws Exception {
         final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
 
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -112,7 +112,7 @@
     }
 
     @Test
-    public void testClose() throws Exception {
+    public void close() throws Exception {
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
         controllerCallback.reset(1);
         mControllerCompat.registerCallback(controllerCallback, sHandler);
@@ -123,7 +123,7 @@
     }
 
     @Test
-    public void testUpdatePlayer() throws Exception {
+    public void updatePlayer() throws Exception {
         final int testState = SessionPlayer.PLAYER_STATE_PLAYING;
         final int testBufferingPosition = 1500;
         final float testSpeed = 1.5f;
@@ -176,7 +176,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeChangedToRemote() throws Exception {
+    public void updatePlayer_playbackTypeChangedToRemote() throws Exception {
         final int controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
         final int maxVolume = 25;
         final int currentVolume = 10;
@@ -212,7 +212,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeChangedToLocal() throws Exception {
+    public void updatePlayer_playbackTypeChangedToLocal() throws Exception {
         Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder()
                 .setVolumeControlType(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE)
                 .setMaxVolume(10)
@@ -258,7 +258,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeNotChanged_local() throws Exception {
+    public void updatePlayer_playbackTypeNotChanged_local() throws Exception {
         final int legacyStream = AudioManager.STREAM_RING;
         final AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
                 .setLegacyStreamType(legacyStream).build();
@@ -296,7 +296,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeNotChanged_remote() throws Exception {
+    public void updatePlayer_playbackTypeNotChanged_remote() throws Exception {
         Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder()
                 .setVolumeControlType(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE)
                 .setMaxVolume(10)
@@ -347,7 +347,7 @@
     }
 
     @Test
-    public void testPlayerStateChange() throws Exception {
+    public void playerStateChange() throws Exception {
         final int targetState = SessionPlayer.PLAYER_STATE_PLAYING;
 
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -363,7 +363,7 @@
     }
 
     @Test
-    public void testPlaybackSpeedChange() throws Exception {
+    public void playbackSpeedChange() throws Exception {
         final float speed = 1.5f;
 
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -378,7 +378,7 @@
     }
 
     @Test
-    public void testBufferingStateChange() throws Exception {
+    public void bufferingStateChange() throws Exception {
         final List<MediaItem> testPlaylist = MediaTestUtils.createFileMediaItems(3);
         final int testItemIndex = 0;
         final int testBufferingState = SessionPlayer.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
@@ -398,7 +398,7 @@
     }
 
     @Test
-    public void testSeekComplete() throws Exception {
+    public void seekComplete() throws Exception {
         final long testSeekPosition = 1300;
 
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -414,7 +414,7 @@
     }
 
     @Test
-    public void testCurrentMediaItemChange() throws Exception {
+    public void currentMediaItemChange() throws Exception {
         String displayTitle = "displayTitle";
         MediaMetadata metadata = new MediaMetadata.Builder()
                 .putText(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, displayTitle).build();
@@ -441,7 +441,7 @@
     }
 
     @Test
-    public void testPlaylistAndPlaylistMetadataChange() throws Exception {
+    public void playlistAndPlaylistMetadataChange() throws Exception {
         final List<MediaItem> playlist = MediaTestUtils.createFileMediaItems(5);
         final String playlistTitle = "playlistTitle";
         MediaMetadata playlistMetadata = new MediaMetadata.Builder()
@@ -469,7 +469,7 @@
     }
 
     @Test
-    public void testPlaylistAndPlaylistMetadataChange_longList() throws Exception {
+    public void playlistAndPlaylistMetadataChange_longList() throws Exception {
         final String playlistTitle = "playlistTitle";
         MediaMetadata playlistMetadata = new MediaMetadata.Builder()
                 .putText(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, playlistTitle).build();
@@ -505,7 +505,7 @@
     }
 
     @Test
-    public void testPlaylistMetadataChange() throws Exception {
+    public void playlistMetadataChange() throws Exception {
         final String playlistTitle = "playlistTitle";
         MediaMetadata playlistMetadata = new MediaMetadata.Builder()
                 .putText(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, playlistTitle).build();
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
similarity index 93%
rename from media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
rename to media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
index e52d782..9e39b4b 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
@@ -53,7 +53,7 @@
  * Tests {@link MediaBrowser} with {@link MediaBrowserServiceCompat}.
  */
 @LargeTest
-public class MediaBrowserServiceCompatCallbackTestWithMediaBrowser extends MediaSessionTestBase {
+public class MediaBrowserServiceCompatCallbackWithMediaBrowserTest extends MediaSessionTestBase {
     private SessionToken mToken;
 
     @Before
@@ -71,7 +71,7 @@
     }
 
     @Test
-    public void testOnGetRootCalledByGetLibraryRoot() throws InterruptedException {
+    public void onGetRootCalledByGetLibraryRoot() throws InterruptedException {
         final String testMediaId = "testOnGetRootCalledByGetLibraryRoot";
         final Bundle testExtras = new Bundle();
         testExtras.putString(testMediaId, testMediaId);
@@ -100,7 +100,7 @@
     }
 
     @Test
-    public void testOnLoadItemCalledByGetItem() throws InterruptedException {
+    public void onLoadItemCalledByGetItem() throws InterruptedException {
         final String testMediaId = "test_media_item";
         final MediaItem testItem = createMediaItem(testMediaId);
         final CountDownLatch latch = new CountDownLatch(1);
@@ -119,7 +119,7 @@
     }
 
     @Test
-    public void testOnLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
+    public void onLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
         final String testParentId = "test_media_parent";
         final int testPage = 2;
         final int testPageSize = 4;
@@ -140,7 +140,7 @@
     }
 
     @Test
-    public void testOnLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
+    public void onLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
         final String testParentId = "test_media_parent";
         final int testPage = 2;
         final int testPageSize = 4;
@@ -169,7 +169,7 @@
     }
 
     @Test
-    public void testOnLoadChildrenCalledBySubscribe() throws InterruptedException {
+    public void onLoadChildrenCalledBySubscribe() throws InterruptedException {
         final String testParentId = "testOnLoadChildrenCalledBySubscribe";
         final LibraryParams testParams = MediaTestUtils.createLibraryParams();
         final CountDownLatch subscribeLatch = new CountDownLatch(1);
@@ -189,7 +189,7 @@
     }
 
     @Test
-    public void testOnSearchCalledBySearch() throws InterruptedException {
+    public void onSearchCalledBySearch() throws InterruptedException {
         final String testQuery = "search_query";
         final int testPage = 2;
         final int testPageSize = 4;
@@ -214,7 +214,7 @@
     }
 
     @Test
-    public void testOnSearchCalledByGetSearchResult() throws InterruptedException {
+    public void onSearchCalledByGetSearchResult() throws InterruptedException {
         final String testQuery = "search_query";
         final int testPage = 2;
         final int testPageSize = 4;
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
similarity index 94%
rename from media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
rename to media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
index 4f1b9f7..40db1de 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
@@ -81,7 +81,7 @@
  */
 @RunWith(AndroidJUnit4.class)
 @LargeTest
-public class MediaSessionCallbackTestWithMediaControllerCompat extends MediaSessionTestBase {
+public class MediaSessionCallbackWithMediaControllerCompatTest extends MediaSessionTestBase {
     private static final String TAG = "MediaSessionCallbackTestWithMediaControllerCompat";
     private static final long VOLUME_CHANGE_TIMEOUT_MS = 5000L;
 
@@ -153,7 +153,7 @@
     }
 
     @Test
-    public void testDisconnectedAfterTimeout() throws InterruptedException {
+    public void disconnectedAfterTimeout() throws InterruptedException {
         CountDownLatch disconnectedLatch = new CountDownLatch(1);
         try (MediaSession session = new MediaSession.Builder(mContext, mPlayer)
                 .setId("testDisconnectedAfterTimeout")
@@ -186,7 +186,7 @@
     }
 
     @Test
-    public void testConnectedCallbackAfterDisconnectedByTimeout() throws InterruptedException {
+    public void connectedCallbackAfterDisconnectedByTimeout() throws InterruptedException {
         CountDownLatch connectedLatch = new CountDownLatch(1);
         CountDownLatch disconnectedLatch = new CountDownLatch(1);
         try (MediaSession session = new MediaSession.Builder(mContext, mPlayer)
@@ -227,7 +227,7 @@
     }
 
     @Test
-    public void testPlay() {
+    public void play() {
         mController.getTransportControls().play();
         try {
             assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -238,7 +238,7 @@
     }
 
     @Test
-    public void testPause() {
+    public void pause() {
         mController.getTransportControls().pause();
         try {
             assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -249,7 +249,7 @@
     }
 
     @Test
-    public void testStop() {
+    public void stop() {
         // MediaControllerCompat#stop() will call MediaSession#pause() and MediaSession#seekTo(0).
         // Therefore, the latch's initial count is 2.
         MockPlayer player = new MockPlayer(2);
@@ -268,7 +268,7 @@
     }
 
     @Test
-    public void testPrepare() {
+    public void prepare() {
         mController.getTransportControls().prepare();
         try {
             assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -279,7 +279,7 @@
     }
 
     @Test
-    public void testSeekTo() {
+    public void seekTo() {
         final long seekPosition = 12125L;
         mController.getTransportControls().seekTo(seekPosition);
         try {
@@ -292,7 +292,7 @@
     }
 
     @Test
-    public void testSetPlaybackSpeed() {
+    public void setPlaybackSpeed() {
         final float testSpeed = 2.0f;
         mController.getTransportControls().setPlaybackSpeed(testSpeed);
         try {
@@ -305,7 +305,7 @@
     }
 
     @Test
-    public void testAddQueueItem() throws InterruptedException {
+    public void addQueueItem() throws InterruptedException {
         final int playlistSize = 10;
 
         List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -327,7 +327,7 @@
     }
 
     @Test
-    public void testAddQueueItemWithIndex() throws InterruptedException {
+    public void addQueueItemWithIndex() throws InterruptedException {
         final int playlistSize = 10;
 
         List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -351,7 +351,7 @@
     }
 
     @Test
-    public void testRemoveQueueItem() throws InterruptedException {
+    public void removeQueueItem() throws InterruptedException {
         final int playlistSize = 10;
 
         List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -374,21 +374,21 @@
     }
 
     @Test
-    public void testSkipToPrevious() throws InterruptedException {
+    public void skipToPrevious() throws InterruptedException {
         mController.getTransportControls().skipToPrevious();
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         assertTrue(mPlayer.mSkipToPreviousItemCalled);
     }
 
     @Test
-    public void testSkipToNext() throws InterruptedException {
+    public void skipToNext() throws InterruptedException {
         mController.getTransportControls().skipToNext();
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         assertTrue(mPlayer.mSkipToNextItemCalled);
     }
 
     @Test
-    public void testSkipToQueueItem() throws InterruptedException {
+    public void skipToQueueItem() throws InterruptedException {
         final int playlistSize = 10;
 
         List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -408,7 +408,7 @@
     }
 
     @Test
-    public void testSetShuffleMode() throws InterruptedException {
+    public void setShuffleMode() throws InterruptedException {
         final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
         mController.getTransportControls().setShuffleMode(testShuffleMode);
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -418,7 +418,7 @@
     }
 
     @Test
-    public void testSetRepeatMode() throws InterruptedException {
+    public void setRepeatMode() throws InterruptedException {
         final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
         mController.getTransportControls().setRepeatMode(testRepeatMode);
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -428,7 +428,7 @@
     }
 
     @Test
-    public void testSetVolumeTo() throws Exception {
+    public void setVolumeTo() throws Exception {
         final int maxVolume = 100;
         final int currentVolume = 23;
         final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -445,7 +445,7 @@
     }
 
     @Test
-    public void testAdjustVolume() throws Exception {
+    public void adjustVolume() throws Exception {
         final int maxVolume = 100;
         final int currentVolume = 23;
         final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -462,7 +462,7 @@
     }
 
     @Test
-    public void testSetVolumeWithLocalVolume() throws Exception {
+    public void setVolumeWithLocalVolume() throws Exception {
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
             return;
@@ -504,7 +504,7 @@
     }
 
     @Test
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
+    public void adjustVolumeWithLocalVolume() throws Exception {
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
             return;
@@ -547,7 +547,7 @@
     }
 
     @Test
-    public void testSendCommand() throws InterruptedException {
+    public void sendCommand() throws InterruptedException {
         // TODO(jaewan): Need to revisit with the permission.
         final String testCommand = "test_command";
         final Bundle testArgs = new Bundle();
@@ -586,7 +586,7 @@
     }
 
     @Test
-    public void testControllerCallback_sessionRejects() throws Exception {
+    public void controllerCallback_sessionRejects() throws Exception {
         final SessionCallback sessionCallback = new SessionCallback() {
             @Override
             public SessionCommandGroup onConnect(@NonNull MediaSession session,
@@ -611,7 +611,7 @@
     }
 
     @Test
-    public void testFastForward() throws InterruptedException {
+    public void fastForward() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
         final SessionCallback callback = new SessionCallback() {
             @Override
@@ -633,7 +633,7 @@
     }
 
     @Test
-    public void testRewind() throws InterruptedException {
+    public void rewind() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
         final SessionCallback callback = new SessionCallback() {
             @Override
@@ -654,7 +654,7 @@
     }
 
     @Test
-    public void testPrepareFromMediaUri() throws InterruptedException {
+    public void prepareFromMediaUri() throws InterruptedException {
         final Uri mediaId = Uri.parse("foo://bar");
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
@@ -683,7 +683,7 @@
     }
 
     @Test
-    public void testPlayFromMediaUri() throws InterruptedException {
+    public void playFromMediaUri() throws InterruptedException {
         final Uri request = Uri.parse("foo://bar");
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
@@ -712,7 +712,7 @@
     }
 
     @Test
-    public void testPrepareFromMediaId() throws InterruptedException {
+    public void prepareFromMediaId() throws InterruptedException {
         final String request = "media_id";
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
@@ -742,7 +742,7 @@
     }
 
     @Test
-    public void testPlayFromMediaId() throws InterruptedException {
+    public void playFromMediaId() throws InterruptedException {
         final String mediaId = "media_id";
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
@@ -772,7 +772,7 @@
     }
 
     @Test
-    public void testPrepareFromSearch() throws InterruptedException {
+    public void prepareFromSearch() throws InterruptedException {
         final String query = "test_query";
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
@@ -802,7 +802,7 @@
     }
 
     @Test
-    public void testPlayFromSearch() throws InterruptedException {
+    public void playFromSearch() throws InterruptedException {
         final String query = "test_query";
         final Bundle bundle = new Bundle();
         bundle.putString("key", "value");
@@ -832,7 +832,7 @@
     }
 
     @Test
-    public void testSetRating() throws InterruptedException {
+    public void setRating() throws InterruptedException {
         final int ratingType = RatingCompat.RATING_5_STARS;
         final float ratingValue = 3.5f;
         final RatingCompat rating = RatingCompat.newStarRating(ratingType, ratingValue);
@@ -864,7 +864,7 @@
     }
 
     @Test
-    public void testOnCommandCallback() throws InterruptedException {
+    public void onCommandCallback() throws InterruptedException {
         final ArrayList<SessionCommand> commands = new ArrayList<>();
         final CountDownLatch latchForPause = new CountDownLatch(1);
         final SessionCallback callback = new SessionCallback() {
@@ -917,7 +917,7 @@
      */
     @Test
     @LargeTest
-    public void testDeadlock() throws InterruptedException {
+    public void deadlock() throws InterruptedException {
         sHandler.postAndSync(new Runnable() {
             @Override
             public void run() {
@@ -995,7 +995,7 @@
 
     @Test
     @LargeTest
-    public void testControllerAfterSessionIsGone() throws InterruptedException {
+    public void controllerAfterSessionIsGone() throws InterruptedException {
         mSession.close();
         testSessionCallbackIsNotCalled();
 
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
similarity index 95%
rename from media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
rename to media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
index c075943..3c3f3292 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
@@ -70,7 +70,7 @@
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-public class MediaSessionCompatCallbackTestWithMediaController extends MediaSessionTestBase {
+public class MediaSessionCompatCallbackWithMediaControllerTest extends MediaSessionTestBase {
     private static final String TAG = "MediaControllerTest";
 
     // The maximum time to wait for an operation.
@@ -123,7 +123,7 @@
     }
 
     @Test
-    public void testPlay() throws Exception {
+    public void play() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -133,7 +133,7 @@
     }
 
     @Test
-    public void testPause() throws Exception {
+    public void pause() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -143,7 +143,7 @@
     }
 
     @Test
-    public void testPrepare() throws Exception {
+    public void prepare() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -153,7 +153,7 @@
     }
 
     @Test
-    public void testSeekTo() throws Exception {
+    public void seekTo() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -165,7 +165,7 @@
     }
 
     @Test
-    public void testSetPlaybackSpeed() throws Exception {
+    public void setPlaybackSpeed() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -177,7 +177,7 @@
     }
 
     @Test
-    public void testAddPlaylistItem() throws Exception {
+    public void addPlaylistItem() throws Exception {
         final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
         final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
         final String testMediaId = "testAddPlaylistItem";
@@ -197,7 +197,7 @@
     }
 
     @Test
-    public void testRemovePlaylistItem() throws Exception {
+    public void removePlaylistItem() throws Exception {
         final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
         final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
 
@@ -216,7 +216,7 @@
     }
 
     @Test
-    public void testReplacePlaylistItem() throws Exception {
+    public void replacePlaylistItem() throws Exception {
         final int testReplaceIndex = 1;
         // replace = remove + add
         final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
@@ -242,7 +242,7 @@
     }
 
     @Test
-    public void testSkipToPreviousItem() throws Exception {
+    public void skipToPreviousItem() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -252,7 +252,7 @@
     }
 
     @Test
-    public void testSkipToNextItem() throws Exception {
+    public void skipToNextItem() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -262,7 +262,7 @@
     }
 
     @Test
-    public void testSkipToPlaylistItem() throws Exception {
+    public void skipToPlaylistItem() throws Exception {
         final int testSkipToIndex = 1;
         final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
         final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -279,7 +279,7 @@
     }
 
     @Test
-    public void testSetShuffleMode() throws Exception {
+    public void setShuffleMode() throws Exception {
         final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
 
         mSession.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_NONE);
@@ -293,7 +293,7 @@
     }
 
     @Test
-    public void testSetRepeatMode() throws Exception {
+    public void setRepeatMode() throws Exception {
         final int testRepeatMode = SessionPlayer.REPEAT_MODE_ALL;
 
         mSession.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_NONE);
@@ -307,7 +307,7 @@
     }
 
     @Test
-    public void testSetVolumeTo() throws Exception {
+    public void setVolumeTo() throws Exception {
         final int maxVolume = 100;
         final int currentVolume = 23;
         final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -324,7 +324,7 @@
     }
 
     @Test
-    public void testAdjustVolume() throws Exception {
+    public void adjustVolume() throws Exception {
         final int maxVolume = 100;
         final int currentVolume = 23;
         final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -341,7 +341,7 @@
     }
 
     @Test
-    public void testSetVolumeWithLocalVolume() throws Exception {
+    public void setVolumeWithLocalVolume() throws Exception {
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
             return;
@@ -378,7 +378,7 @@
     }
 
     @Test
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
+    public void adjustVolumeWithLocalVolume() throws Exception {
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
             return;
@@ -417,7 +417,7 @@
     }
 
     @Test
-    public void testSendCustomCommand() throws Exception {
+    public void sendCustomCommand() throws Exception {
         final String command = "test_custom_command";
         final Bundle testArgs = new Bundle();
         testArgs.putString("args", "test_args");
@@ -433,7 +433,7 @@
     }
 
     @Test
-    public void testFastForward() throws Exception {
+    public void fastForward() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -443,7 +443,7 @@
     }
 
     @Test
-    public void testRewind() throws Exception {
+    public void rewind() throws Exception {
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
 
@@ -453,7 +453,7 @@
     }
 
     @Test
-    public void testSetRating() throws Exception {
+    public void setRating() throws Exception {
         final float ratingValue = 3.5f;
         final Rating rating2 = new StarRating(5, ratingValue);
         final String mediaId = "media_id";
diff --git a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
similarity index 94%
rename from media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
rename to media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
index 17a9dfd..1331de22 100644
--- a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
+++ b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
@@ -67,8 +67,8 @@
  * Tests whether {@link MediaBrowserCompat} works well with {@link MediaLibraryService}.
  */
 @LargeTest
-public class MediaBrowserCompatTestWithMediaLibraryService extends
-        MediaBrowserCompatTestWithMediaSessionService {
+public class MediaBrowserCompatWithMediaLibraryServiceTest extends
+        MediaBrowserCompatWithMediaSessionServiceTest {
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -85,7 +85,7 @@
     }
 
     @Test
-    public void testGetRoot() throws InterruptedException {
+    public void getRoot() throws InterruptedException {
         prepareLooper();
         // The MockMediaLibraryService gives MediaBrowserConstants.ROOT_ID as root ID, and
         // MediaBrowserConstants.ROOT_EXTRAS as extras.
@@ -105,7 +105,7 @@
     }
 
     @Test
-    public void testGetItem() throws InterruptedException {
+    public void getItem() throws InterruptedException {
         prepareLooper();
         final String mediaId = MEDIA_ID_GET_ITEM;
 
@@ -123,7 +123,7 @@
     }
 
     @Test
-    public void testGetItem_nullResult() throws InterruptedException {
+    public void getItem_nullResult() throws InterruptedException {
         prepareLooper();
         final String mediaId = "random_media_id";
 
@@ -145,7 +145,7 @@
     }
 
     @Test
-    public void testGetChildren() throws InterruptedException {
+    public void getChildren() throws InterruptedException {
         prepareLooper();
         final String testParentId = PARENT_ID;
 
@@ -174,7 +174,7 @@
     }
 
     @Test
-    public void testGetChildren_withLongList() throws InterruptedException {
+    public void getChildren_withLongList() throws InterruptedException {
         prepareLooper();
         final String testParentId = PARENT_ID_LONG_LIST;
 
@@ -203,7 +203,7 @@
     }
 
     @Test
-    public void testGetChildren_withPagination() throws InterruptedException {
+    public void getChildren_withPagination() throws InterruptedException {
         prepareLooper();
         final String testParentId = PARENT_ID;
         final int page = 4;
@@ -246,7 +246,7 @@
     }
 
     @Test
-    public void testGetChildren_emptyResult() throws InterruptedException {
+    public void getChildren_emptyResult() throws InterruptedException {
         prepareLooper();
         final String testParentId = PARENT_ID_NO_CHILDREN;
 
@@ -264,7 +264,7 @@
     }
 
     @Test
-    public void testGetChildren_nullResult() throws InterruptedException {
+    public void getChildren_nullResult() throws InterruptedException {
         prepareLooper();
         final String testParentId = PARENT_ID_ERROR;
 
@@ -287,7 +287,7 @@
     }
 
     @Test
-    public void testSearch() throws InterruptedException {
+    public void search() throws InterruptedException {
         prepareLooper();
         final String testQuery = SEARCH_QUERY;
         final int page = 4;
@@ -326,7 +326,7 @@
     }
 
     @Test
-    public void testSearch_withLongList() throws InterruptedException {
+    public void search_withLongList() throws InterruptedException {
         prepareLooper();
         final String testQuery = SEARCH_QUERY_LONG_LIST;
         final int page = 0;
@@ -356,7 +356,7 @@
     }
 
     @Test
-    public void testSearch_emptyResult() throws InterruptedException {
+    public void search_emptyResult() throws InterruptedException {
         prepareLooper();
         final String testQuery = SEARCH_QUERY_EMPTY_RESULT;
         final Bundle testExtras = new Bundle();
@@ -378,7 +378,7 @@
     }
 
     @Test
-    public void testSearch_error() throws InterruptedException {
+    public void search_error() throws InterruptedException {
         prepareLooper();
         final String testQuery = SEARCH_QUERY_ERROR;
         final Bundle testExtras = new Bundle();
@@ -404,7 +404,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribe() throws InterruptedException {
+    public void subscribe() throws InterruptedException {
 //        prepareLooper();
 //        final String testParentId = "testSubscribeId";
 //        final List<MediaItem> testList = TestUtils.createMediaItems(3);
@@ -450,7 +450,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribe_withExtras() throws InterruptedException {
+    public void subscribe_withExtras() throws InterruptedException {
 //        prepareLooper();
 //        final String testParentId = "testSubscribe_withExtras";
 //        final Bundle testExtras = new Bundle();
@@ -502,7 +502,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribe_withPagination() throws InterruptedException {
+    public void subscribe_withPagination() throws InterruptedException {
 //        prepareLooper();
 //        final String testParentId = "testSubscribe_pagination_ID";
 //        final List<MediaItem> testList = TestUtils.createMediaItems(3);
@@ -569,7 +569,7 @@
 
     @Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testSubscribeAndUnsubscribe() throws InterruptedException {
+    public void subscribeAndUnsubscribe() throws InterruptedException {
 //        prepareLooper();
 //        final String testParentId = "testUnsubscribe";
 //        final Bundle testExtras = new Bundle();
@@ -610,7 +610,7 @@
 
     @Ignore("TODO: Split this test to here and MediaLibrarySessionLegacyCallbackTest.")
     @Test
-    public void testNotifyChildrenChanged() throws InterruptedException {
+    public void notifyChildrenChanged() throws InterruptedException {
 //        prepareLooper();
 //        final String testSubscribedParentId = "testNotifyChildrenChanged";
 //        final String testUnsubscribedParentId = "testNotifyChildrenChanged22";
@@ -664,7 +664,7 @@
 
     // TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
     @Test
-    public void testCustomAction() throws InterruptedException {
+    public void customAction() throws InterruptedException {
         prepareLooper();
         final Bundle testArgs = new Bundle();
         testArgs.putString("args_key", "args_value");
@@ -685,7 +685,7 @@
 
     // TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
     @Test
-    public void testCustomAction_rejected() throws InterruptedException {
+    public void customAction_rejected() throws InterruptedException {
         prepareLooper();
         // This action will not be allowed by the library session.
         final String testAction = "random_custom_action";
diff --git a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
similarity index 93%
rename from media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
rename to media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
index 7c04129..94d3f10 100644
--- a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
+++ b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
@@ -41,7 +41,7 @@
  * Tests whether {@link MediaBrowserCompat} works well with {@link MediaSessionService}.
  */
 @LargeTest
-public class MediaBrowserCompatTestWithMediaSessionService extends MediaSessionTestBase {
+public class MediaBrowserCompatWithMediaSessionServiceTest extends MediaSessionTestBase {
     MediaBrowserCompat mBrowserCompat;
     TestConnectionCallback mConnectionCallback;
 
@@ -79,7 +79,7 @@
     }
 
     @Test
-    public void testConnect() throws InterruptedException {
+    public void connect() throws InterruptedException {
         prepareLooper();
         connectAndWait();
         assertNotEquals(0, mConnectionCallback.mFailedLatch.getCount());
@@ -87,7 +87,7 @@
 
     @Ignore
     @Test
-    public void testConnect_rejected() throws InterruptedException {
+    public void connect_rejected() throws InterruptedException {
         prepareLooper();
         // TODO: Connect the browser to the session service whose onConnect() returns null.
         assertTrue(mConnectionCallback.mFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -95,7 +95,7 @@
     }
 
     @Test
-    public void testGetSessionToken() throws Exception {
+    public void getSessionToken() throws Exception {
         prepareLooper();
         connectAndWait();
         MediaControllerCompat controller = new MediaControllerCompat(mContext,
diff --git a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
similarity index 95%
rename from media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
rename to media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
index 0532b3c..407d7ca 100644
--- a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
+++ b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
@@ -57,7 +57,7 @@
  */
 @RunWith(AndroidJUnit4.class)
 @LargeTest
-public class MediaControllerCompatCallbackTestWithMediaSession extends MediaSessionTestBase {
+public class MediaControllerCompatCallbackWithMediaSessionTest extends MediaSessionTestBase {
     private static final String TAG = "MCCCallbackTestWithMS2";
 
     private static final long TIMEOUT_MS = 1000L;
@@ -81,7 +81,7 @@
     }
 
     @Test
-    public void testRepeatModeChange() throws Exception {
+    public void repeatModeChange() throws Exception {
         prepareLooper();
         final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
 
@@ -97,7 +97,7 @@
     }
 
     @Test
-    public void testShuffleModeChange() throws Exception {
+    public void shuffleModeChange() throws Exception {
         prepareLooper();
         final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
 
@@ -113,7 +113,7 @@
     }
 
     @Test
-    public void testClose() throws Exception {
+    public void close() throws Exception {
         prepareLooper();
         final MediaControllerCallback controllerCallback = new MediaControllerCallback();
         controllerCallback.reset(1);
@@ -125,7 +125,7 @@
     }
 
     @Test
-    public void testUpdatePlayer() throws Exception {
+    public void updatePlayer() throws Exception {
         prepareLooper();
         final int testState = SessionPlayer.PLAYER_STATE_PLAYING;
         final int testBufferingPosition = 1500;
@@ -175,7 +175,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeChangedToRemote() throws Exception {
+    public void updatePlayer_playbackTypeChangedToRemote() throws Exception {
         prepareLooper();
         final int controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
         final int maxVolume = 25;
@@ -209,7 +209,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeChangedToLocal() throws Exception {
+    public void updatePlayer_playbackTypeChangedToLocal() throws Exception {
         prepareLooper();
         Bundle prevPlayerConfig = RemoteMediaSession.createMockPlayerConnectorConfig(
                 VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 10 /* maxVolume */,
@@ -253,7 +253,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeNotChanged_local() throws Exception {
+    public void updatePlayer_playbackTypeNotChanged_local() throws Exception {
         final int legacyStream = AudioManager.STREAM_RING;
         final AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
                 .setLegacyStreamType(legacyStream).build();
@@ -290,7 +290,7 @@
     }
 
     @Test
-    public void testUpdatePlayer_playbackTypeNotChanged_remote() throws Exception {
+    public void updatePlayer_playbackTypeNotChanged_remote() throws Exception {
         prepareLooper();
         Bundle prevPlayerConfig = RemoteMediaSession.createMockPlayerConnectorConfig(
                 VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 10 /* maxVolume */,
@@ -337,7 +337,7 @@
     }
 
     @Test
-    public void testPlayerStateChange() throws Exception {
+    public void playerStateChange() throws Exception {
         prepareLooper();
         final int targetState = SessionPlayer.PLAYER_STATE_PLAYING;
 
@@ -354,7 +354,7 @@
     }
 
     @Test
-    public void testPlaybackSpeedChange() throws Exception {
+    public void playbackSpeedChange() throws Exception {
         prepareLooper();
         final float speed = 1.5f;
 
@@ -370,7 +370,7 @@
     }
 
     @Test
-    public void testBufferingStateChange() throws Exception {
+    public void bufferingStateChange() throws Exception {
         prepareLooper();
         final List<MediaItem> testPlaylist = MediaTestUtils.createFileMediaItems(3);
         final int testItemIndex = 0;
@@ -391,7 +391,7 @@
     }
 
     @Test
-    public void testSeekComplete() throws Exception {
+    public void seekComplete() throws Exception {
         prepareLooper();
         final long testSeekPosition = 1300;
 
@@ -408,7 +408,7 @@
     }
 
     @Test
-    public void testCurrentMediaItemChange() throws Exception {
+    public void currentMediaItemChange() throws Exception {
         prepareLooper();
 
         String displayTitle = "displayTitle";
@@ -437,7 +437,7 @@
     }
 
     @Test
-    public void testPlaylistAndPlaylistMetadataChange() throws Exception {
+    public void playlistAndPlaylistMetadataChange() throws Exception {
         prepareLooper();
         final List<MediaItem> playlist = MediaTestUtils.createFileMediaItems(5);
         final String playlistTitle = "playlistTitle";
@@ -466,7 +466,7 @@
     }
 
     @Test
-    public void testPlaylistAndPlaylistMetadataChange_longList() throws Exception {
+    public void playlistAndPlaylistMetadataChange_longList() throws Exception {
         prepareLooper();
         final String playlistTitle = "playlistTitle";
         MediaMetadata playlistMetadata = new MediaMetadata.Builder()
@@ -503,7 +503,7 @@
     }
 
     @Test
-    public void testPlaylistMetadataChange() throws Exception {
+    public void playlistMetadataChange() throws Exception {
         prepareLooper();
         final String playlistTitle = "playlistTitle";
         MediaMetadata playlistMetadata = new MediaMetadata.Builder()
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
similarity index 93%
rename from media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
rename to media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
index c94f144..f0bd07f 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
@@ -53,7 +53,7 @@
  * Tests {@link MediaBrowser} with {@link MediaBrowserServiceCompat}.
  */
 @LargeTest
-public class MediaBrowserServiceCompatCallbackTestWithMediaBrowser extends MediaSessionTestBase {
+public class MediaBrowserServiceCompatCallbackWithMediaBrowserTest extends MediaSessionTestBase {
     private SessionToken mToken;
 
     @Before
@@ -71,7 +71,7 @@
     }
 
     @Test
-    public void testOnGetRootCalledByGetLibraryRoot() throws InterruptedException {
+    public void onGetRootCalledByGetLibraryRoot() throws InterruptedException {
         prepareLooper();
         final String testMediaId = "testOnGetRootCalledByGetLibraryRoot";
         final Bundle testExtras = new Bundle();
@@ -101,7 +101,7 @@
     }
 
     @Test
-    public void testOnLoadItemCalledByGetItem() throws InterruptedException {
+    public void onLoadItemCalledByGetItem() throws InterruptedException {
         prepareLooper();
         final String testMediaId = "test_media_item";
         final MediaItem testItem = createMediaItem(testMediaId);
@@ -121,7 +121,7 @@
     }
 
     @Test
-    public void testOnLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
+    public void onLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
         prepareLooper();
         final String testParentId = "test_media_parent";
         final int testPage = 2;
@@ -143,7 +143,7 @@
     }
 
     @Test
-    public void testOnLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
+    public void onLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
         prepareLooper();
         final String testParentId = "test_media_parent";
         final int testPage = 2;
@@ -173,7 +173,7 @@
     }
 
     @Test
-    public void testOnLoadChildrenCalledBySubscribe() throws InterruptedException {
+    public void onLoadChildrenCalledBySubscribe() throws InterruptedException {
         prepareLooper();
         final String testParentId = "testOnLoadChildrenCalledBySubscribe";
         final LibraryParams testParams = MediaTestUtils.createLibraryParams();
@@ -194,7 +194,7 @@
     }
 
     @Test
-    public void testOnSearchCalledBySearch() throws InterruptedException {
+    public void onSearchCalledBySearch() throws InterruptedException {
         prepareLooper();
         final String testQuery = "search_query";
         final int testPage = 2;
@@ -220,7 +220,7 @@
     }
 
     @Test
-    public void testOnSearchCalledByGetSearchResult() throws InterruptedException {
+    public void onSearchCalledByGetSearchResult() throws InterruptedException {
         prepareLooper();
         final String testQuery = "search_query";
         final int testPage = 2;
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
similarity index 94%
rename from media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
rename to media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
index 63c46aa..443d768 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
@@ -80,7 +80,7 @@
  */
 @RunWith(AndroidJUnit4.class)
 @LargeTest
-public class MediaSessionCallbackTestWithMediaControllerCompat extends MediaSessionTestBase {
+public class MediaSessionCallbackWithMediaControllerCompatTest extends MediaSessionTestBase {
     private static final String TAG = "MediaSessionCallbackTestWithMediaControllerCompat";
     private static final long VOLUME_CHANGE_TIMEOUT_MS = 5000L;
 
@@ -145,7 +145,7 @@
     }
 
     @Test
-    public void testPlay() {
+    public void play() {
         prepareLooper();
         mController.getTransportControls().play();
         try {
@@ -157,7 +157,7 @@
     }
 
     @Test
-    public void testPause() {
+    public void pause() {
         prepareLooper();
         mController.getTransportControls().pause();
         try {
@@ -169,7 +169,7 @@
     }
 
     @Test
-    public void testStop() {
+    public void stop() {
         prepareLooper();
 
         // MediaControllerCompat#stop() will call MediaSession#pause() and MediaSession#seekTo(0).
@@ -190,7 +190,7 @@
     }
 
     @Test
-    public void testPrepare() {
+    public void prepare() {
         prepareLooper();
         mController.getTransportControls().prepare();
         try {
@@ -202,7 +202,7 @@
     }
 
     @Test
-    public void testSeekTo() {
+    public void seekTo() {
         prepareLooper();
         final long seekPosition = 12125L;
         mController.getTransportControls().seekTo(seekPosition);
@@ -216,7 +216,7 @@
     }
 
     @Test
-    public void testAddQueueItem() throws InterruptedException {
+    public void addQueueItem() throws InterruptedException {
         prepareLooper();
         final int playlistSize = 10;
 
@@ -239,7 +239,7 @@
     }
 
     @Test
-    public void testAddQueueItemWithIndex() throws InterruptedException {
+    public void addQueueItemWithIndex() throws InterruptedException {
         prepareLooper();
         final int playlistSize = 10;
 
@@ -264,7 +264,7 @@
     }
 
     @Test
-    public void testRemoveQueueItem() throws InterruptedException {
+    public void removeQueueItem() throws InterruptedException {
         prepareLooper();
         final int playlistSize = 10;
 
@@ -288,7 +288,7 @@
     }
 
     @Test
-    public void testSkipToPrevious() throws InterruptedException {
+    public void skipToPrevious() throws InterruptedException {
         prepareLooper();
         mController.getTransportControls().skipToPrevious();
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -296,7 +296,7 @@
     }
 
     @Test
-    public void testSkipToNext() throws InterruptedException {
+    public void skipToNext() throws InterruptedException {
         prepareLooper();
         mController.getTransportControls().skipToNext();
         assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -304,7 +304,7 @@
     }
 
     @Test
-    public void testSkipToQueueItem() throws InterruptedException {
+    public void skipToQueueItem() throws InterruptedException {
         prepareLooper();
         final int playlistSize = 10;
 
@@ -325,7 +325,7 @@
     }
 
     @Test
-    public void testSetShuffleMode() throws InterruptedException {
+    public void setShuffleMode() throws InterruptedException {
         prepareLooper();
         final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
         mController.getTransportControls().setShuffleMode(testShuffleMode);
@@ -336,7 +336,7 @@
     }
 
     @Test
-    public void testSetRepeatMode() throws InterruptedException {
+    public void setRepeatMode() throws InterruptedException {
         prepareLooper();
         final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
         mController.getTransportControls().setRepeatMode(testRepeatMode);
@@ -347,7 +347,7 @@
     }
 
     @Test
-    public void testSetVolumeTo() throws Exception {
+    public void setVolumeTo() throws Exception {
         prepareLooper();
         final int maxVolume = 100;
         final int currentVolume = 23;
@@ -365,7 +365,7 @@
     }
 
     @Test
-    public void testAdjustVolume() throws Exception {
+    public void adjustVolume() throws Exception {
         prepareLooper();
         final int maxVolume = 100;
         final int currentVolume = 23;
@@ -383,7 +383,7 @@
     }
 
     @Test
-    public void testSetVolumeWithLocalVolume() throws Exception {
+    public void setVolumeWithLocalVolume() throws Exception {
         prepareLooper();
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
@@ -426,7 +426,7 @@
     }
 
     @Test
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
+    public void adjustVolumeWithLocalVolume() throws Exception {
         prepareLooper();
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
@@ -470,7 +470,7 @@
     }
 
     @Test
-    public void testSendCommand() throws InterruptedException {
+    public void sendCommand() throws InterruptedException {
         prepareLooper();
         // TODO(jaewan): Need to revisit with the permission.
         final String testCommand = "test_command";
@@ -508,7 +508,7 @@
     }
 
     @Test
-    public void testControllerCallback_sessionRejects() throws Exception {
+    public void controllerCallback_sessionRejects() throws Exception {
         prepareLooper();
         final SessionCallback sessionCallback = new SessionCallback() {
             @Override
@@ -534,7 +534,7 @@
     }
 
     @Test
-    public void testFastForward() throws InterruptedException {
+    public void fastForward() throws InterruptedException {
         prepareLooper();
         final CountDownLatch latch = new CountDownLatch(1);
         final SessionCallback callback = new SessionCallback() {
@@ -556,7 +556,7 @@
     }
 
     @Test
-    public void testRewind() throws InterruptedException {
+    public void rewind() throws InterruptedException {
         prepareLooper();
         final CountDownLatch latch = new CountDownLatch(1);
         final SessionCallback callback = new SessionCallback() {
@@ -578,7 +578,7 @@
     }
 
     @Test
-    public void testPlayFromSearch() throws InterruptedException {
+    public void playFromSearch() throws InterruptedException {
         prepareLooper();
         final String request = "random query";
         final Bundle bundle = new Bundle();
@@ -607,7 +607,7 @@
     }
 
     @Test
-    public void testPlayFromUri() throws InterruptedException {
+    public void playFromUri() throws InterruptedException {
         prepareLooper();
         final Uri request = Uri.parse("foo://boo");
         final Bundle bundle = new Bundle();
@@ -635,7 +635,7 @@
     }
 
     @Test
-    public void testPlayFromMediaId() throws InterruptedException {
+    public void playFromMediaId() throws InterruptedException {
         prepareLooper();
         final String request = "media_id";
         final Bundle bundle = new Bundle();
@@ -663,7 +663,7 @@
     }
 
     @Test
-    public void testPrepareFromSearch() throws InterruptedException {
+    public void prepareFromSearch() throws InterruptedException {
         prepareLooper();
         final String request = "random query";
         final Bundle bundle = new Bundle();
@@ -691,7 +691,7 @@
     }
 
     @Test
-    public void testPrepareFromUri() throws InterruptedException {
+    public void prepareFromUri() throws InterruptedException {
         prepareLooper();
         final Uri request = Uri.parse("foo://boo");
         final Bundle bundle = new Bundle();
@@ -719,7 +719,7 @@
     }
 
     @Test
-    public void testPrepareFromMediaId() throws InterruptedException {
+    public void prepareFromMediaId() throws InterruptedException {
         prepareLooper();
         final String request = "media_id";
         final Bundle bundle = new Bundle();
@@ -747,7 +747,7 @@
     }
 
     @Test
-    public void testSetRating() throws InterruptedException {
+    public void setRating() throws InterruptedException {
         prepareLooper();
         final int ratingType = RatingCompat.RATING_5_STARS;
         final float ratingValue = 3.5f;
@@ -779,7 +779,7 @@
     }
 
     @Test
-    public void testOnCommandCallback() throws InterruptedException {
+    public void onCommandCallback() throws InterruptedException {
         prepareLooper();
         final ArrayList<SessionCommand> commands = new ArrayList<>();
         final CountDownLatch latchForPause = new CountDownLatch(1);
@@ -833,7 +833,7 @@
      */
     @Test
     @LargeTest
-    public void testDeadlock() throws InterruptedException {
+    public void deadlock() throws InterruptedException {
         prepareLooper();
         sHandler.postAndSync(new Runnable() {
             @Override
@@ -912,7 +912,7 @@
 
     @Test
     @LargeTest
-    public void testControllerAfterSessionIsGone() throws InterruptedException {
+    public void controllerAfterSessionIsGone() throws InterruptedException {
         prepareLooper();
         mSession.close();
         testSessionCallbackIsNotCalled();
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
similarity index 95%
rename from media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
rename to media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
index b45271c..34c30d96 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
@@ -70,7 +70,7 @@
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-public class MediaSessionCompatCallbackTestWithMediaController extends MediaSessionTestBase {
+public class MediaSessionCompatCallbackWithMediaControllerTest extends MediaSessionTestBase {
     private static final String TAG = "MediaControllerTest";
 
     // The maximum time to wait for an operation.
@@ -127,7 +127,7 @@
     }
 
     @Test
-    public void testPlay() throws Exception {
+    public void play() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -138,7 +138,7 @@
     }
 
     @Test
-    public void testPause() throws Exception {
+    public void pause() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -149,7 +149,7 @@
     }
 
     @Test
-    public void testPrepare() throws Exception {
+    public void prepare() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -160,7 +160,7 @@
     }
 
     @Test
-    public void testSeekTo() throws Exception {
+    public void seekTo() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -173,7 +173,7 @@
     }
 
     @Test
-    public void testAddPlaylistItem() throws Exception {
+    public void addPlaylistItem() throws Exception {
         prepareLooper();
         final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
         final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -194,7 +194,7 @@
     }
 
     @Test
-    public void testRemovePlaylistItem() throws Exception {
+    public void removePlaylistItem() throws Exception {
         prepareLooper();
         final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
         final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -214,7 +214,7 @@
     }
 
     @Test
-    public void testReplacePlaylistItem() throws Exception {
+    public void replacePlaylistItem() throws Exception {
         prepareLooper();
         final int testReplaceIndex = 1;
         // replace = remove + add
@@ -241,7 +241,7 @@
     }
 
     @Test
-    public void testSkipToPreviousItem() throws Exception {
+    public void skipToPreviousItem() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -252,7 +252,7 @@
     }
 
     @Test
-    public void testSkipToNextItem() throws Exception {
+    public void skipToNextItem() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -263,7 +263,7 @@
     }
 
     @Test
-    public void testSkipToPlaylistItem() throws Exception {
+    public void skipToPlaylistItem() throws Exception {
         prepareLooper();
 
         final int testSkipToIndex = 1;
@@ -282,7 +282,7 @@
     }
 
     @Test
-    public void testSetShuffleMode() throws Exception {
+    public void setShuffleMode() throws Exception {
         prepareLooper();
         final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
 
@@ -297,7 +297,7 @@
     }
 
     @Test
-    public void testSetRepeatMode() throws Exception {
+    public void setRepeatMode() throws Exception {
         prepareLooper();
         final int testRepeatMode = SessionPlayer.REPEAT_MODE_ALL;
 
@@ -312,7 +312,7 @@
     }
 
     @Test
-    public void testSetVolumeTo() throws Exception {
+    public void setVolumeTo() throws Exception {
         prepareLooper();
         final int maxVolume = 100;
         final int currentVolume = 23;
@@ -330,7 +330,7 @@
     }
 
     @Test
-    public void testAdjustVolume() throws Exception {
+    public void adjustVolume() throws Exception {
         prepareLooper();
         final int maxVolume = 100;
         final int currentVolume = 23;
@@ -348,7 +348,7 @@
     }
 
     @Test
-    public void testSetVolumeWithLocalVolume() throws Exception {
+    public void setVolumeWithLocalVolume() throws Exception {
         prepareLooper();
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
@@ -386,7 +386,7 @@
     }
 
     @Test
-    public void testAdjustVolumeWithLocalVolume() throws Exception {
+    public void adjustVolumeWithLocalVolume() throws Exception {
         prepareLooper();
         if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
             // This test is not eligible for this device.
@@ -426,7 +426,7 @@
     }
 
     @Test
-    public void testSendCustomCommand() throws Exception {
+    public void sendCustomCommand() throws Exception {
         prepareLooper();
         final String command = "test_custom_command";
         final Bundle testArgs = new Bundle();
@@ -443,7 +443,7 @@
     }
 
     @Test
-    public void testFastForward() throws Exception {
+    public void fastForward() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -454,7 +454,7 @@
     }
 
     @Test
-    public void testRewind() throws Exception {
+    public void rewind() throws Exception {
         prepareLooper();
         RemoteMediaController controller = createControllerAndWaitConnection();
         mSessionCallback.reset(1);
@@ -465,7 +465,7 @@
     }
 
     @Test
-    public void testSetRating() throws Exception {
+    public void setRating() throws Exception {
         prepareLooper();
         final float ratingValue = 3.5f;
         final Rating rating2 = new StarRating(5, ratingValue);
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
index 751cdfbe..8629127 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
@@ -176,6 +176,16 @@
                 MediaRouter2Utils.KEY_MESSENGER);
     }
 
+    @Nullable
+    static String getSessionIdForRouteController(@Nullable RouteController controller) {
+        if (!(controller instanceof DynamicMediaRoute2Controller)) {
+            return null;
+        }
+        MediaRouter2.RoutingController routingController =
+                ((DynamicMediaRoute2Controller) controller).mRoutingController;
+        return (routingController == null) ? null : routingController.getId();
+    }
+
     private class RouteCallback extends MediaRouter2.RouteCallback {
         RouteCallback() {}
 
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java
index af7b763..cac56397 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java
@@ -54,6 +54,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -279,6 +280,7 @@
                 (descriptor == null) ? Collections.emptyList() : descriptor.getRoutes();
         // Handle duplicated IDs
         notifyRoutes(routeDescriptors.stream().map(MediaRouter2Utils::toFwkMediaRoute2Info)
+                .filter(Objects::nonNull)
                 .collect(Collectors.toMap(r -> r.getId(), r -> r, (a, b) -> b)).values());
     }
 
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
index 4eb5d6d..bccb6de 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -3181,6 +3181,7 @@
             return -1;
         }
 
+        @SuppressLint("NewApi")
         private void updatePlaybackInfoFromSelectedRoute() {
             if (mSelectedRoute != null) {
                 mPlaybackInfo.volume = mSelectedRoute.getVolume();
@@ -3188,6 +3189,12 @@
                 mPlaybackInfo.volumeHandling = mSelectedRoute.getVolumeHandling();
                 mPlaybackInfo.playbackStream = mSelectedRoute.getPlaybackStream();
                 mPlaybackInfo.playbackType = mSelectedRoute.getPlaybackType();
+                if (mTransferEnabled && mSelectedRoute.getProviderInstance() == mMr2Provider) {
+                    mPlaybackInfo.volumeControlId = MediaRoute2Provider
+                            .getSessionIdForRouteController(mSelectedRouteController);
+                } else {
+                    mPlaybackInfo.volumeControlId = null;
+                }
 
                 final int count = mRemoteControlClients.size();
                 for (int i = 0; i < count; i++) {
@@ -3207,7 +3214,7 @@
                             controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
                         }
                         mMediaSession.configureVolume(controlType, mPlaybackInfo.volumeMax,
-                                mPlaybackInfo.volume);
+                                mPlaybackInfo.volume, mPlaybackInfo.volumeControlId);
                     }
                 }
             } else {
@@ -3300,7 +3307,7 @@
             }
 
             public void configureVolume(@VolumeProviderCompat.ControlType int controlType,
-                    int max, int current) {
+                    int max, int current, @Nullable String volumeControlId) {
                 if (mMsCompat != null) {
                     if (mVpCompat != null && controlType == mControlType && max == mMaxVolume) {
                         // If we haven't changed control type or max just set the
@@ -3308,7 +3315,8 @@
                         mVpCompat.setCurrentVolume(current);
                     } else {
                         // Otherwise create a new provider and update
-                        mVpCompat = new VolumeProviderCompat(controlType, max, current) {
+                        mVpCompat = new VolumeProviderCompat(controlType, max, current,
+                                volumeControlId) {
                             @Override
                             public void onSetVolumeTo(final int volume) {
                                 mCallbackHandler.post(new Runnable() {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java
index f006a82..93f3879 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java
@@ -19,6 +19,7 @@
 import android.media.AudioManager;
 import android.os.Build;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import java.lang.ref.WeakReference;
@@ -77,6 +78,8 @@
         public int volumeHandling = MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED;
         public int playbackStream = AudioManager.STREAM_MUSIC;
         public int playbackType = MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
+        @Nullable
+        public String volumeControlId;
     }
 
     /**
diff --git a/navigation/benchmark/src/androidTest/AndroidManifest.xml b/navigation/benchmark/src/androidTest/AndroidManifest.xml
index 03cb61f..358a851 100644
--- a/navigation/benchmark/src/androidTest/AndroidManifest.xml
+++ b/navigation/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
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 e812316..4c95e72 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
@@ -205,7 +205,10 @@
         return mSavedStateHandle;
     }
 
-    // Copied from LifecycleRegistry.getStateAfter()
+    /**
+     * Copied from LifecycleRegistry.getStateAfter()
+     * TODO: update to Event.getTargetState() when navigation's lifecycle-core dependency is updated
+     */
     @NonNull
     private static Lifecycle.State getStateAfter(@NonNull Lifecycle.Event event) {
         switch (event) {
diff --git a/paging/common/api/3.0.0-alpha03.txt b/paging/common/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..dd27c13
--- /dev/null
+++ b/paging/common/api/3.0.0-alpha03.txt
@@ -0,0 +1,457 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  public final class CachedPagingDataKt {
+    method @CheckResult public static <T> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>> cachedIn(kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+  }
+
+  public final class CancelableChannelFlowKt {
+  }
+
+  public final class CombinedLoadStates {
+    ctor public CombinedLoadStates(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+    method public androidx.paging.LoadStates component1();
+    method public androidx.paging.LoadStates? component2();
+    method public androidx.paging.CombinedLoadStates copy(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+    method public androidx.paging.LoadState getAppend();
+    method public androidx.paging.LoadStates? getMediator();
+    method public androidx.paging.LoadState getPrepend();
+    method public androidx.paging.LoadState getRefresh();
+    method public androidx.paging.LoadStates getSource();
+    property public final androidx.paging.LoadState append;
+    property public final androidx.paging.LoadState prepend;
+    property public final androidx.paging.LoadState refresh;
+  }
+
+  public abstract class DataSource<Key, Value> {
+    method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+    method @AnyThread public final void addInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    method @AnyThread public void invalidate();
+    method @WorkerThread public boolean isInvalid();
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+    method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+    method @AnyThread public final void removeInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    property @WorkerThread public boolean isInvalid;
+  }
+
+  public abstract static class DataSource.Factory<Key, Value> {
+    ctor public DataSource.Factory();
+    method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = Dispatchers.IO);
+    method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory();
+    method public abstract androidx.paging.DataSource<Key,Value> create();
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  public static interface DataSource.InvalidatedCallback {
+    method @AnyThread public void onInvalidated();
+  }
+
+  @kotlin.RequiresOptIn public @interface ExperimentalPagingApi {
+  }
+
+  @Deprecated public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+    ctor @Deprecated public ItemKeyedDataSource();
+    method @Deprecated public abstract Key getKey(Value item);
+    method @Deprecated public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+    method @Deprecated public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+    method @Deprecated public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value> callback);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  @Deprecated public abstract static class ItemKeyedDataSource.LoadCallback<Value> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data);
+  }
+
+  @Deprecated public abstract static class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback<Value> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount);
+  }
+
+  @Deprecated public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadInitialParams(Key? requestedInitialKey, int requestedLoadSize, boolean placeholdersEnabled);
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final Key? requestedInitialKey;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public static class ItemKeyedDataSource.LoadParams<Key> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+    field @Deprecated public final Key key;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  public abstract sealed class LoadState {
+    method public final boolean getEndOfPaginationReached();
+  }
+
+  public static final class LoadState.Error extends androidx.paging.LoadState {
+    ctor public LoadState.Error(Throwable error);
+    method public Throwable getError();
+  }
+
+  public static final class LoadState.Loading extends androidx.paging.LoadState {
+    field public static final androidx.paging.LoadState.Loading INSTANCE;
+  }
+
+  public static final class LoadState.NotLoading extends androidx.paging.LoadState {
+    ctor public LoadState.NotLoading(boolean endOfPaginationReached);
+  }
+
+  public final class LoadStates {
+    ctor public LoadStates(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+    method public androidx.paging.LoadState component1();
+    method public androidx.paging.LoadState component2();
+    method public androidx.paging.LoadState component3();
+    method public androidx.paging.LoadStates copy(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+    method public androidx.paging.LoadState getAppend();
+    method public androidx.paging.LoadState getPrepend();
+    method public androidx.paging.LoadState getRefresh();
+  }
+
+  public enum LoadType {
+    method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.LoadType[] values();
+    enum_constant public static final androidx.paging.LoadType APPEND;
+    enum_constant public static final androidx.paging.LoadType PREPEND;
+    enum_constant public static final androidx.paging.LoadType REFRESH;
+  }
+
+  public final class PageEventKt {
+  }
+
+  @Deprecated public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+    ctor @Deprecated public PageKeyedDataSource();
+    method @Deprecated public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+    method @Deprecated public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+    method @Deprecated public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key,Value> callback);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  @Deprecated public abstract static class PageKeyedDataSource.LoadCallback<Key, Value> {
+    ctor @Deprecated public PageKeyedDataSource.LoadCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? adjacentPageKey);
+  }
+
+  @Deprecated public abstract static class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+    ctor @Deprecated public PageKeyedDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount, Key? previousPageKey, Key? nextPageKey);
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? previousPageKey, Key? nextPageKey);
+  }
+
+  @Deprecated public static class PageKeyedDataSource.LoadInitialParams<Key> {
+    ctor @Deprecated public PageKeyedDataSource.LoadInitialParams(int requestedLoadSize, boolean placeholdersEnabled);
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public static class PageKeyedDataSource.LoadParams<Key> {
+    ctor @Deprecated public PageKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+    field @Deprecated public final Key key;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public abstract class PagedList<T> extends java.util.AbstractList<T> {
+    method @Deprecated public final void addWeakCallback(java.util.List<? extends T>? previousSnapshot, androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void addWeakCallback(androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void addWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public abstract void detach();
+    method @Deprecated public T? get(int index);
+    method @Deprecated public final androidx.paging.PagedList.Config getConfig();
+    method @Deprecated public final androidx.paging.DataSource<?,T> getDataSource();
+    method @Deprecated public abstract Object? getLastKey();
+    method @Deprecated public final int getLoadedCount();
+    method @Deprecated public final int getPositionOffset();
+    method @Deprecated public int getSize();
+    method @Deprecated public abstract boolean isDetached();
+    method @Deprecated public boolean isImmutable();
+    method @Deprecated public final void loadAround(int index);
+    method @Deprecated public final void removeWeakCallback(androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void removeWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void retry();
+    method @Deprecated public final java.util.List<T> snapshot();
+    property @Deprecated public final androidx.paging.DataSource<?,T> dataSource;
+    property public abstract boolean isDetached;
+    property public boolean isImmutable;
+    property public abstract Object? lastKey;
+    property public final int loadedCount;
+    property public final int positionOffset;
+    property public int size;
+  }
+
+  @Deprecated @MainThread public abstract static class PagedList.BoundaryCallback<T> {
+    ctor @Deprecated public PagedList.BoundaryCallback();
+    method @Deprecated public void onItemAtEndLoaded(T itemAtEnd);
+    method @Deprecated public void onItemAtFrontLoaded(T itemAtFront);
+    method @Deprecated public void onZeroItemsLoaded();
+  }
+
+  @Deprecated public static final class PagedList.Builder<Key, Value> {
+    ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, int pageSize);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, androidx.paging.PagedList.Config config);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, int pageSize);
+    method @Deprecated public androidx.paging.PagedList<Value> build();
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchDispatcher(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setInitialKey(Key? initialKey);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyDispatcher(kotlinx.coroutines.CoroutineDispatcher notifyDispatcher);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyExecutor(java.util.concurrent.Executor notifyExecutor);
+  }
+
+  @Deprecated public abstract static class PagedList.Callback {
+    ctor @Deprecated public PagedList.Callback();
+    method @Deprecated public abstract void onChanged(int position, int count);
+    method @Deprecated public abstract void onInserted(int position, int count);
+    method @Deprecated public abstract void onRemoved(int position, int count);
+  }
+
+  @Deprecated public static final class PagedList.Config {
+    field @Deprecated public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+    field @Deprecated public final boolean enablePlaceholders;
+    field @Deprecated public final int initialLoadSizeHint;
+    field @Deprecated public final int maxSize;
+    field @Deprecated public final int pageSize;
+    field @Deprecated public final int prefetchDistance;
+  }
+
+  @Deprecated public static final class PagedList.Config.Builder {
+    ctor @Deprecated public PagedList.Config.Builder();
+    method @Deprecated public androidx.paging.PagedList.Config build();
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean enablePlaceholders);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(@IntRange(from=1) int initialLoadSizeHint);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setMaxSize(@IntRange(from=2) int maxSize);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setPageSize(@IntRange(from=1) int pageSize);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setPrefetchDistance(@IntRange(from=0) int prefetchDistance);
+  }
+
+  public final class PagedListConfigKt {
+    method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * androidx.paging.PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = 2147483647);
+  }
+
+  public final class PagedListKt {
+    method @Deprecated public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
+  }
+
+  public final class Pager<Key, Value> {
+    ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, androidx.paging.RemoteMediator<Key,Value>? remoteMediator, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    ctor public Pager(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> getFlow();
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> flow;
+  }
+
+  public final class PagingConfig {
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize, int jumpThreshold);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
+    ctor public PagingConfig(int pageSize);
+    field public static final androidx.paging.PagingConfig.Companion Companion;
+    field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+    field public final boolean enablePlaceholders;
+    field public final int initialLoadSize;
+    field public final int jumpThreshold;
+    field public final int maxSize;
+    field public final int pageSize;
+    field public final int prefetchDistance;
+  }
+
+  public static final class PagingConfig.Companion {
+  }
+
+  public final class PagingData<T> {
+    method public static <T> androidx.paging.PagingData<T> empty();
+    method @CheckResult public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+    method @CheckResult public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
+    method @CheckResult public androidx.paging.PagingData<T> insertFooterItem(T item);
+    method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
+    method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    field public static final androidx.paging.PagingData.Companion Companion;
+  }
+
+  public static final class PagingData.Companion {
+    method public <T> androidx.paging.PagingData<T> empty();
+    method @CheckResult public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
+  public final class PagingDataKt {
+    method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
+  public abstract class PagingSource<Key, Value> {
+    ctor public PagingSource();
+    method public final boolean getInvalid();
+    method public boolean getJumpingSupported();
+    method public boolean getKeyReuseSupported();
+    method @androidx.paging.ExperimentalPagingApi public Key? getRefreshKey(androidx.paging.PagingState<Key,Value> state);
+    method public void invalidate();
+    method public abstract suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+    method public final void registerInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    method public final void unregisterInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    property public final boolean invalid;
+    property public boolean jumpingSupported;
+    property public boolean keyReuseSupported;
+  }
+
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method @Deprecated public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled);
+    method public Key? getKey();
+  }
+
+  public abstract static sealed class PagingSource.LoadResult<Key, Value> {
+  }
+
+  public static final class PagingSource.LoadResult.Error<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+    ctor public PagingSource.LoadResult.Error(Throwable throwable);
+    method public Throwable component1();
+    method public androidx.paging.PagingSource.LoadResult.Error<Key,Value> copy(Throwable throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class PagingSource.LoadResult.Page<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+    ctor public PagingSource.LoadResult.Page(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, @IntRange(from=null) int itemsBefore, @IntRange(from=null) int itemsAfter);
+    method public java.util.List<Value> component1();
+    method public Key? component2();
+    method public Key? component3();
+    method public int component4();
+    method public int component5();
+    method public androidx.paging.PagingSource.LoadResult.Page<Key,Value> copy(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, int itemsBefore, int itemsAfter);
+    method public java.util.List<Value> getData();
+    method public int getItemsAfter();
+    method public int getItemsBefore();
+    method public Key? getNextKey();
+    method public Key? getPrevKey();
+    field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
+    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
+  }
+
+  public static final class PagingSource.LoadResult.Page.Companion {
+  }
+
+  public final class PagingSourceKt {
+  }
+
+  public final class PagingState<Key, Value> {
+    method public Value? closestItemToPosition(int anchorPosition);
+    method public androidx.paging.PagingSource.LoadResult.Page<Key,Value>? closestPageToPosition(int anchorPosition);
+    method public Value? firstItemOrNull();
+    method public Integer? getAnchorPosition();
+    method public androidx.paging.PagingConfig getConfig();
+    method public java.util.List<androidx.paging.PagingSource.LoadResult.Page<Key,Value>> getPages();
+    method public boolean isEmpty();
+    method public Value? lastItemOrNull();
+  }
+
+  @Deprecated public abstract class PositionalDataSource<T> extends androidx.paging.DataSource<java.lang.Integer,T> {
+    ctor @Deprecated public PositionalDataSource();
+    method @Deprecated public static final int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams params, int totalCount);
+    method @Deprecated public static final int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams params, int initialLoadPosition, int totalCount);
+    method @Deprecated @WorkerThread public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+    method @Deprecated @WorkerThread public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T,V> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(kotlin.jvm.functions.Function1<? super T,? extends V> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>,java.util.List<V>> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends T>,? extends java.util.List<? extends V>> function);
+  }
+
+  @Deprecated public abstract static class PositionalDataSource.LoadInitialCallback<T> {
+    ctor @Deprecated public PositionalDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position, int totalCount);
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position);
+  }
+
+  @Deprecated public static class PositionalDataSource.LoadInitialParams {
+    ctor @Deprecated public PositionalDataSource.LoadInitialParams(int requestedStartPosition, int requestedLoadSize, int pageSize, boolean placeholdersEnabled);
+    field @Deprecated public final int pageSize;
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final int requestedLoadSize;
+    field @Deprecated public final int requestedStartPosition;
+  }
+
+  @Deprecated public abstract static class PositionalDataSource.LoadRangeCallback<T> {
+    ctor @Deprecated public PositionalDataSource.LoadRangeCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data);
+  }
+
+  @Deprecated public static class PositionalDataSource.LoadRangeParams {
+    ctor @Deprecated public PositionalDataSource.LoadRangeParams(int startPosition, int loadSize);
+    field @Deprecated public final int loadSize;
+    field @Deprecated public final int startPosition;
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class RemoteMediator<Key, Value> {
+    ctor public RemoteMediator();
+    method public suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> $completion);
+    method public abstract suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+  }
+
+  public enum RemoteMediator.InitializeAction {
+    method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.RemoteMediator.InitializeAction[] values();
+    enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
+    enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
+  }
+
+  public abstract static sealed class RemoteMediator.MediatorResult {
+  }
+
+  public static final class RemoteMediator.MediatorResult.Error extends androidx.paging.RemoteMediator.MediatorResult {
+    ctor public RemoteMediator.MediatorResult.Error(Throwable throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class RemoteMediator.MediatorResult.Success extends androidx.paging.RemoteMediator.MediatorResult {
+    ctor public RemoteMediator.MediatorResult.Success(boolean endOfPaginationReached);
+    method public boolean endOfPaginationReached();
+  }
+
+  public final class SeparatorsKt {
+  }
+
+}
+
+package androidx.paging.multicast {
+
+  public final class ChannelManagerKt {
+  }
+
+}
+
diff --git a/paging/common/api/current.txt b/paging/common/api/current.txt
index 351532f..dd27c13 100644
--- a/paging/common/api/current.txt
+++ b/paging/common/api/current.txt
@@ -100,7 +100,7 @@
   }
 
   public static final class LoadState.Loading extends androidx.paging.LoadState {
-    field public static final androidx.paging.LoadState.Loading! INSTANCE;
+    field public static final androidx.paging.LoadState.Loading INSTANCE;
   }
 
   public static final class LoadState.NotLoading extends androidx.paging.LoadState {
@@ -119,6 +119,8 @@
   }
 
   public enum LoadType {
+    method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.LoadType[] values();
     enum_constant public static final androidx.paging.LoadType APPEND;
     enum_constant public static final androidx.paging.LoadType PREPEND;
     enum_constant public static final androidx.paging.LoadType REFRESH;
@@ -260,7 +262,7 @@
     ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
     ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
     ctor public PagingConfig(int pageSize);
-    field public static final androidx.paging.PagingConfig.Companion! Companion;
+    field public static final androidx.paging.PagingConfig.Companion Companion;
     field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
     field public final boolean enablePlaceholders;
     field public final int initialLoadSize;
@@ -281,7 +283,7 @@
     method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
     method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
-    field public static final androidx.paging.PagingData.Companion! Companion;
+    field public static final androidx.paging.PagingData.Companion Companion;
   }
 
   public static final class PagingData.Companion {
@@ -358,7 +360,7 @@
     method public Key? getNextKey();
     method public Key? getPrevKey();
     field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
-    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion! Companion;
+    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
   }
 
   public static final class PagingSource.LoadResult.Page.Companion {
@@ -422,6 +424,8 @@
   }
 
   public enum RemoteMediator.InitializeAction {
+    method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.RemoteMediator.InitializeAction[] values();
     enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
     enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
   }
diff --git a/paging/common/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/common/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..0776c3e
--- /dev/null
+++ b/paging/common/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,459 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  public final class CachedPagingDataKt {
+    method @CheckResult public static <T> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>> cachedIn(kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+  }
+
+  public final class CancelableChannelFlowKt {
+  }
+
+  public final class CombinedLoadStates {
+    ctor public CombinedLoadStates(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+    method public androidx.paging.LoadStates component1();
+    method public androidx.paging.LoadStates? component2();
+    method public androidx.paging.CombinedLoadStates copy(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public inline void forEach(kotlin.jvm.functions.Function3<? super androidx.paging.LoadType,? super java.lang.Boolean,? super androidx.paging.LoadState,kotlin.Unit> op);
+    method public androidx.paging.LoadState getAppend();
+    method public androidx.paging.LoadStates? getMediator();
+    method public androidx.paging.LoadState getPrepend();
+    method public androidx.paging.LoadState getRefresh();
+    method public androidx.paging.LoadStates getSource();
+    property public final androidx.paging.LoadState append;
+    property public final androidx.paging.LoadState prepend;
+    property public final androidx.paging.LoadState refresh;
+  }
+
+  public abstract class DataSource<Key, Value> {
+    method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+    method @AnyThread public final void addInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    method @AnyThread public void invalidate();
+    method @WorkerThread public boolean isInvalid();
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+    method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+    method @AnyThread public final void removeInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    property @WorkerThread public boolean isInvalid;
+  }
+
+  public abstract static class DataSource.Factory<Key, Value> {
+    ctor public DataSource.Factory();
+    method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = Dispatchers.IO);
+    method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory();
+    method public abstract androidx.paging.DataSource<Key,Value> create();
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  public static interface DataSource.InvalidatedCallback {
+    method @AnyThread public void onInvalidated();
+  }
+
+  @kotlin.RequiresOptIn public @interface ExperimentalPagingApi {
+  }
+
+  @Deprecated public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+    ctor @Deprecated public ItemKeyedDataSource();
+    method @Deprecated public abstract Key getKey(Value item);
+    method @Deprecated public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+    method @Deprecated public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+    method @Deprecated public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value> callback);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  @Deprecated public abstract static class ItemKeyedDataSource.LoadCallback<Value> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data);
+  }
+
+  @Deprecated public abstract static class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback<Value> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount);
+  }
+
+  @Deprecated public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadInitialParams(Key? requestedInitialKey, int requestedLoadSize, boolean placeholdersEnabled);
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final Key? requestedInitialKey;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public static class ItemKeyedDataSource.LoadParams<Key> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+    field @Deprecated public final Key key;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  public abstract sealed class LoadState {
+    method public final boolean getEndOfPaginationReached();
+  }
+
+  public static final class LoadState.Error extends androidx.paging.LoadState {
+    ctor public LoadState.Error(Throwable error);
+    method public Throwable getError();
+  }
+
+  public static final class LoadState.Loading extends androidx.paging.LoadState {
+    field public static final androidx.paging.LoadState.Loading INSTANCE;
+  }
+
+  public static final class LoadState.NotLoading extends androidx.paging.LoadState {
+    ctor public LoadState.NotLoading(boolean endOfPaginationReached);
+  }
+
+  public final class LoadStates {
+    ctor public LoadStates(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+    method public androidx.paging.LoadState component1();
+    method public androidx.paging.LoadState component2();
+    method public androidx.paging.LoadState component3();
+    method public androidx.paging.LoadStates copy(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public inline void forEach(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> op);
+    method public androidx.paging.LoadState getAppend();
+    method public androidx.paging.LoadState getPrepend();
+    method public androidx.paging.LoadState getRefresh();
+  }
+
+  public enum LoadType {
+    method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.LoadType[] values();
+    enum_constant public static final androidx.paging.LoadType APPEND;
+    enum_constant public static final androidx.paging.LoadType PREPEND;
+    enum_constant public static final androidx.paging.LoadType REFRESH;
+  }
+
+  public final class PageEventKt {
+  }
+
+  @Deprecated public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+    ctor @Deprecated public PageKeyedDataSource();
+    method @Deprecated public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+    method @Deprecated public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+    method @Deprecated public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key,Value> callback);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  @Deprecated public abstract static class PageKeyedDataSource.LoadCallback<Key, Value> {
+    ctor @Deprecated public PageKeyedDataSource.LoadCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? adjacentPageKey);
+  }
+
+  @Deprecated public abstract static class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+    ctor @Deprecated public PageKeyedDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount, Key? previousPageKey, Key? nextPageKey);
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? previousPageKey, Key? nextPageKey);
+  }
+
+  @Deprecated public static class PageKeyedDataSource.LoadInitialParams<Key> {
+    ctor @Deprecated public PageKeyedDataSource.LoadInitialParams(int requestedLoadSize, boolean placeholdersEnabled);
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public static class PageKeyedDataSource.LoadParams<Key> {
+    ctor @Deprecated public PageKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+    field @Deprecated public final Key key;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public abstract class PagedList<T> extends java.util.AbstractList<T> {
+    method @Deprecated public final void addWeakCallback(java.util.List<? extends T>? previousSnapshot, androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void addWeakCallback(androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void addWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public abstract void detach();
+    method @Deprecated public T? get(int index);
+    method @Deprecated public final androidx.paging.PagedList.Config getConfig();
+    method @Deprecated public final androidx.paging.DataSource<?,T> getDataSource();
+    method @Deprecated public abstract Object? getLastKey();
+    method @Deprecated public final int getLoadedCount();
+    method @Deprecated public final int getPositionOffset();
+    method @Deprecated public int getSize();
+    method @Deprecated public abstract boolean isDetached();
+    method @Deprecated public boolean isImmutable();
+    method @Deprecated public final void loadAround(int index);
+    method @Deprecated public final void removeWeakCallback(androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void removeWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void retry();
+    method @Deprecated public final java.util.List<T> snapshot();
+    property @Deprecated public final androidx.paging.DataSource<?,T> dataSource;
+    property public abstract boolean isDetached;
+    property public boolean isImmutable;
+    property public abstract Object? lastKey;
+    property public final int loadedCount;
+    property public final int positionOffset;
+    property public int size;
+  }
+
+  @Deprecated @MainThread public abstract static class PagedList.BoundaryCallback<T> {
+    ctor @Deprecated public PagedList.BoundaryCallback();
+    method @Deprecated public void onItemAtEndLoaded(T itemAtEnd);
+    method @Deprecated public void onItemAtFrontLoaded(T itemAtFront);
+    method @Deprecated public void onZeroItemsLoaded();
+  }
+
+  @Deprecated public static final class PagedList.Builder<Key, Value> {
+    ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, int pageSize);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, androidx.paging.PagedList.Config config);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, int pageSize);
+    method @Deprecated public androidx.paging.PagedList<Value> build();
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchDispatcher(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setInitialKey(Key? initialKey);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyDispatcher(kotlinx.coroutines.CoroutineDispatcher notifyDispatcher);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyExecutor(java.util.concurrent.Executor notifyExecutor);
+  }
+
+  @Deprecated public abstract static class PagedList.Callback {
+    ctor @Deprecated public PagedList.Callback();
+    method @Deprecated public abstract void onChanged(int position, int count);
+    method @Deprecated public abstract void onInserted(int position, int count);
+    method @Deprecated public abstract void onRemoved(int position, int count);
+  }
+
+  @Deprecated public static final class PagedList.Config {
+    field @Deprecated public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+    field @Deprecated public final boolean enablePlaceholders;
+    field @Deprecated public final int initialLoadSizeHint;
+    field @Deprecated public final int maxSize;
+    field @Deprecated public final int pageSize;
+    field @Deprecated public final int prefetchDistance;
+  }
+
+  @Deprecated public static final class PagedList.Config.Builder {
+    ctor @Deprecated public PagedList.Config.Builder();
+    method @Deprecated public androidx.paging.PagedList.Config build();
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean enablePlaceholders);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(@IntRange(from=1) int initialLoadSizeHint);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setMaxSize(@IntRange(from=2) int maxSize);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setPageSize(@IntRange(from=1) int pageSize);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setPrefetchDistance(@IntRange(from=0) int prefetchDistance);
+  }
+
+  public final class PagedListConfigKt {
+    method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * androidx.paging.PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = 2147483647);
+  }
+
+  public final class PagedListKt {
+    method @Deprecated public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
+  }
+
+  public final class Pager<Key, Value> {
+    ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, androidx.paging.RemoteMediator<Key,Value>? remoteMediator, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    ctor public Pager(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> getFlow();
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> flow;
+  }
+
+  public final class PagingConfig {
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize, int jumpThreshold);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
+    ctor public PagingConfig(int pageSize);
+    field public static final androidx.paging.PagingConfig.Companion Companion;
+    field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+    field public final boolean enablePlaceholders;
+    field public final int initialLoadSize;
+    field public final int jumpThreshold;
+    field public final int maxSize;
+    field public final int pageSize;
+    field public final int prefetchDistance;
+  }
+
+  public static final class PagingConfig.Companion {
+  }
+
+  public final class PagingData<T> {
+    method public static <T> androidx.paging.PagingData<T> empty();
+    method @CheckResult public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+    method @CheckResult public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
+    method @CheckResult public androidx.paging.PagingData<T> insertFooterItem(T item);
+    method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
+    method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    field public static final androidx.paging.PagingData.Companion Companion;
+  }
+
+  public static final class PagingData.Companion {
+    method public <T> androidx.paging.PagingData<T> empty();
+    method @CheckResult public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
+  public final class PagingDataKt {
+    method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
+  public abstract class PagingSource<Key, Value> {
+    ctor public PagingSource();
+    method public final boolean getInvalid();
+    method public boolean getJumpingSupported();
+    method public boolean getKeyReuseSupported();
+    method @androidx.paging.ExperimentalPagingApi public Key? getRefreshKey(androidx.paging.PagingState<Key,Value> state);
+    method public void invalidate();
+    method public abstract suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+    method public final void registerInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    method public final void unregisterInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    property public final boolean invalid;
+    property public boolean jumpingSupported;
+    property public boolean keyReuseSupported;
+  }
+
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method @Deprecated public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled);
+    method public Key? getKey();
+  }
+
+  public abstract static sealed class PagingSource.LoadResult<Key, Value> {
+  }
+
+  public static final class PagingSource.LoadResult.Error<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+    ctor public PagingSource.LoadResult.Error(Throwable throwable);
+    method public Throwable component1();
+    method public androidx.paging.PagingSource.LoadResult.Error<Key,Value> copy(Throwable throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class PagingSource.LoadResult.Page<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+    ctor public PagingSource.LoadResult.Page(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, @IntRange(from=null) int itemsBefore, @IntRange(from=null) int itemsAfter);
+    method public java.util.List<Value> component1();
+    method public Key? component2();
+    method public Key? component3();
+    method public int component4();
+    method public int component5();
+    method public androidx.paging.PagingSource.LoadResult.Page<Key,Value> copy(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, int itemsBefore, int itemsAfter);
+    method public java.util.List<Value> getData();
+    method public int getItemsAfter();
+    method public int getItemsBefore();
+    method public Key? getNextKey();
+    method public Key? getPrevKey();
+    field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
+    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
+  }
+
+  public static final class PagingSource.LoadResult.Page.Companion {
+  }
+
+  public final class PagingSourceKt {
+  }
+
+  public final class PagingState<Key, Value> {
+    method public Value? closestItemToPosition(int anchorPosition);
+    method public androidx.paging.PagingSource.LoadResult.Page<Key,Value>? closestPageToPosition(int anchorPosition);
+    method public Value? firstItemOrNull();
+    method public Integer? getAnchorPosition();
+    method public androidx.paging.PagingConfig getConfig();
+    method public java.util.List<androidx.paging.PagingSource.LoadResult.Page<Key,Value>> getPages();
+    method public boolean isEmpty();
+    method public Value? lastItemOrNull();
+  }
+
+  @Deprecated public abstract class PositionalDataSource<T> extends androidx.paging.DataSource<java.lang.Integer,T> {
+    ctor @Deprecated public PositionalDataSource();
+    method @Deprecated public static final int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams params, int totalCount);
+    method @Deprecated public static final int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams params, int initialLoadPosition, int totalCount);
+    method @Deprecated @WorkerThread public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+    method @Deprecated @WorkerThread public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T,V> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(kotlin.jvm.functions.Function1<? super T,? extends V> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>,java.util.List<V>> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends T>,? extends java.util.List<? extends V>> function);
+  }
+
+  @Deprecated public abstract static class PositionalDataSource.LoadInitialCallback<T> {
+    ctor @Deprecated public PositionalDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position, int totalCount);
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position);
+  }
+
+  @Deprecated public static class PositionalDataSource.LoadInitialParams {
+    ctor @Deprecated public PositionalDataSource.LoadInitialParams(int requestedStartPosition, int requestedLoadSize, int pageSize, boolean placeholdersEnabled);
+    field @Deprecated public final int pageSize;
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final int requestedLoadSize;
+    field @Deprecated public final int requestedStartPosition;
+  }
+
+  @Deprecated public abstract static class PositionalDataSource.LoadRangeCallback<T> {
+    ctor @Deprecated public PositionalDataSource.LoadRangeCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data);
+  }
+
+  @Deprecated public static class PositionalDataSource.LoadRangeParams {
+    ctor @Deprecated public PositionalDataSource.LoadRangeParams(int startPosition, int loadSize);
+    field @Deprecated public final int loadSize;
+    field @Deprecated public final int startPosition;
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class RemoteMediator<Key, Value> {
+    ctor public RemoteMediator();
+    method public suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> $completion);
+    method public abstract suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+  }
+
+  public enum RemoteMediator.InitializeAction {
+    method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.RemoteMediator.InitializeAction[] values();
+    enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
+    enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
+  }
+
+  public abstract static sealed class RemoteMediator.MediatorResult {
+  }
+
+  public static final class RemoteMediator.MediatorResult.Error extends androidx.paging.RemoteMediator.MediatorResult {
+    ctor public RemoteMediator.MediatorResult.Error(Throwable throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class RemoteMediator.MediatorResult.Success extends androidx.paging.RemoteMediator.MediatorResult {
+    ctor public RemoteMediator.MediatorResult.Success(boolean endOfPaginationReached);
+    method public boolean endOfPaginationReached();
+  }
+
+  public final class SeparatorsKt {
+  }
+
+}
+
+package androidx.paging.multicast {
+
+  public final class ChannelManagerKt {
+  }
+
+}
+
diff --git a/paging/common/api/public_plus_experimental_current.txt b/paging/common/api/public_plus_experimental_current.txt
index a634c55..0776c3e 100644
--- a/paging/common/api/public_plus_experimental_current.txt
+++ b/paging/common/api/public_plus_experimental_current.txt
@@ -101,7 +101,7 @@
   }
 
   public static final class LoadState.Loading extends androidx.paging.LoadState {
-    field public static final androidx.paging.LoadState.Loading! INSTANCE;
+    field public static final androidx.paging.LoadState.Loading INSTANCE;
   }
 
   public static final class LoadState.NotLoading extends androidx.paging.LoadState {
@@ -121,6 +121,8 @@
   }
 
   public enum LoadType {
+    method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.LoadType[] values();
     enum_constant public static final androidx.paging.LoadType APPEND;
     enum_constant public static final androidx.paging.LoadType PREPEND;
     enum_constant public static final androidx.paging.LoadType REFRESH;
@@ -262,7 +264,7 @@
     ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
     ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
     ctor public PagingConfig(int pageSize);
-    field public static final androidx.paging.PagingConfig.Companion! Companion;
+    field public static final androidx.paging.PagingConfig.Companion Companion;
     field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
     field public final boolean enablePlaceholders;
     field public final int initialLoadSize;
@@ -283,7 +285,7 @@
     method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
     method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
-    field public static final androidx.paging.PagingData.Companion! Companion;
+    field public static final androidx.paging.PagingData.Companion Companion;
   }
 
   public static final class PagingData.Companion {
@@ -360,7 +362,7 @@
     method public Key? getNextKey();
     method public Key? getPrevKey();
     field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
-    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion! Companion;
+    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
   }
 
   public static final class PagingSource.LoadResult.Page.Companion {
@@ -424,6 +426,8 @@
   }
 
   public enum RemoteMediator.InitializeAction {
+    method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.RemoteMediator.InitializeAction[] values();
     enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
     enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
   }
diff --git a/paging/common/api/restricted_3.0.0-alpha03.txt b/paging/common/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..dd27c13
--- /dev/null
+++ b/paging/common/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,457 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  public final class CachedPagingDataKt {
+    method @CheckResult public static <T> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>> cachedIn(kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+  }
+
+  public final class CancelableChannelFlowKt {
+  }
+
+  public final class CombinedLoadStates {
+    ctor public CombinedLoadStates(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+    method public androidx.paging.LoadStates component1();
+    method public androidx.paging.LoadStates? component2();
+    method public androidx.paging.CombinedLoadStates copy(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+    method public androidx.paging.LoadState getAppend();
+    method public androidx.paging.LoadStates? getMediator();
+    method public androidx.paging.LoadState getPrepend();
+    method public androidx.paging.LoadState getRefresh();
+    method public androidx.paging.LoadStates getSource();
+    property public final androidx.paging.LoadState append;
+    property public final androidx.paging.LoadState prepend;
+    property public final androidx.paging.LoadState refresh;
+  }
+
+  public abstract class DataSource<Key, Value> {
+    method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+    method @AnyThread public final void addInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    method @AnyThread public void invalidate();
+    method @WorkerThread public boolean isInvalid();
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+    method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+    method @AnyThread public final void removeInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    property @WorkerThread public boolean isInvalid;
+  }
+
+  public abstract static class DataSource.Factory<Key, Value> {
+    ctor public DataSource.Factory();
+    method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = Dispatchers.IO);
+    method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory();
+    method public abstract androidx.paging.DataSource<Key,Value> create();
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  public static interface DataSource.InvalidatedCallback {
+    method @AnyThread public void onInvalidated();
+  }
+
+  @kotlin.RequiresOptIn public @interface ExperimentalPagingApi {
+  }
+
+  @Deprecated public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+    ctor @Deprecated public ItemKeyedDataSource();
+    method @Deprecated public abstract Key getKey(Value item);
+    method @Deprecated public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+    method @Deprecated public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+    method @Deprecated public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value> callback);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  @Deprecated public abstract static class ItemKeyedDataSource.LoadCallback<Value> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data);
+  }
+
+  @Deprecated public abstract static class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback<Value> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount);
+  }
+
+  @Deprecated public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadInitialParams(Key? requestedInitialKey, int requestedLoadSize, boolean placeholdersEnabled);
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final Key? requestedInitialKey;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public static class ItemKeyedDataSource.LoadParams<Key> {
+    ctor @Deprecated public ItemKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+    field @Deprecated public final Key key;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  public abstract sealed class LoadState {
+    method public final boolean getEndOfPaginationReached();
+  }
+
+  public static final class LoadState.Error extends androidx.paging.LoadState {
+    ctor public LoadState.Error(Throwable error);
+    method public Throwable getError();
+  }
+
+  public static final class LoadState.Loading extends androidx.paging.LoadState {
+    field public static final androidx.paging.LoadState.Loading INSTANCE;
+  }
+
+  public static final class LoadState.NotLoading extends androidx.paging.LoadState {
+    ctor public LoadState.NotLoading(boolean endOfPaginationReached);
+  }
+
+  public final class LoadStates {
+    ctor public LoadStates(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+    method public androidx.paging.LoadState component1();
+    method public androidx.paging.LoadState component2();
+    method public androidx.paging.LoadState component3();
+    method public androidx.paging.LoadStates copy(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+    method public androidx.paging.LoadState getAppend();
+    method public androidx.paging.LoadState getPrepend();
+    method public androidx.paging.LoadState getRefresh();
+  }
+
+  public enum LoadType {
+    method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.LoadType[] values();
+    enum_constant public static final androidx.paging.LoadType APPEND;
+    enum_constant public static final androidx.paging.LoadType PREPEND;
+    enum_constant public static final androidx.paging.LoadType REFRESH;
+  }
+
+  public final class PageEventKt {
+  }
+
+  @Deprecated public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+    ctor @Deprecated public PageKeyedDataSource();
+    method @Deprecated public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+    method @Deprecated public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+    method @Deprecated public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key,Value> callback);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+    method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+  }
+
+  @Deprecated public abstract static class PageKeyedDataSource.LoadCallback<Key, Value> {
+    ctor @Deprecated public PageKeyedDataSource.LoadCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? adjacentPageKey);
+  }
+
+  @Deprecated public abstract static class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+    ctor @Deprecated public PageKeyedDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount, Key? previousPageKey, Key? nextPageKey);
+    method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? previousPageKey, Key? nextPageKey);
+  }
+
+  @Deprecated public static class PageKeyedDataSource.LoadInitialParams<Key> {
+    ctor @Deprecated public PageKeyedDataSource.LoadInitialParams(int requestedLoadSize, boolean placeholdersEnabled);
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public static class PageKeyedDataSource.LoadParams<Key> {
+    ctor @Deprecated public PageKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+    field @Deprecated public final Key key;
+    field @Deprecated public final int requestedLoadSize;
+  }
+
+  @Deprecated public abstract class PagedList<T> extends java.util.AbstractList<T> {
+    method @Deprecated public final void addWeakCallback(java.util.List<? extends T>? previousSnapshot, androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void addWeakCallback(androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void addWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public abstract void detach();
+    method @Deprecated public T? get(int index);
+    method @Deprecated public final androidx.paging.PagedList.Config getConfig();
+    method @Deprecated public final androidx.paging.DataSource<?,T> getDataSource();
+    method @Deprecated public abstract Object? getLastKey();
+    method @Deprecated public final int getLoadedCount();
+    method @Deprecated public final int getPositionOffset();
+    method @Deprecated public int getSize();
+    method @Deprecated public abstract boolean isDetached();
+    method @Deprecated public boolean isImmutable();
+    method @Deprecated public final void loadAround(int index);
+    method @Deprecated public final void removeWeakCallback(androidx.paging.PagedList.Callback callback);
+    method @Deprecated public final void removeWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void retry();
+    method @Deprecated public final java.util.List<T> snapshot();
+    property @Deprecated public final androidx.paging.DataSource<?,T> dataSource;
+    property public abstract boolean isDetached;
+    property public boolean isImmutable;
+    property public abstract Object? lastKey;
+    property public final int loadedCount;
+    property public final int positionOffset;
+    property public int size;
+  }
+
+  @Deprecated @MainThread public abstract static class PagedList.BoundaryCallback<T> {
+    ctor @Deprecated public PagedList.BoundaryCallback();
+    method @Deprecated public void onItemAtEndLoaded(T itemAtEnd);
+    method @Deprecated public void onItemAtFrontLoaded(T itemAtFront);
+    method @Deprecated public void onZeroItemsLoaded();
+  }
+
+  @Deprecated public static final class PagedList.Builder<Key, Value> {
+    ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, int pageSize);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, androidx.paging.PagedList.Config config);
+    ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, int pageSize);
+    method @Deprecated public androidx.paging.PagedList<Value> build();
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchDispatcher(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setInitialKey(Key? initialKey);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyDispatcher(kotlinx.coroutines.CoroutineDispatcher notifyDispatcher);
+    method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyExecutor(java.util.concurrent.Executor notifyExecutor);
+  }
+
+  @Deprecated public abstract static class PagedList.Callback {
+    ctor @Deprecated public PagedList.Callback();
+    method @Deprecated public abstract void onChanged(int position, int count);
+    method @Deprecated public abstract void onInserted(int position, int count);
+    method @Deprecated public abstract void onRemoved(int position, int count);
+  }
+
+  @Deprecated public static final class PagedList.Config {
+    field @Deprecated public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+    field @Deprecated public final boolean enablePlaceholders;
+    field @Deprecated public final int initialLoadSizeHint;
+    field @Deprecated public final int maxSize;
+    field @Deprecated public final int pageSize;
+    field @Deprecated public final int prefetchDistance;
+  }
+
+  @Deprecated public static final class PagedList.Config.Builder {
+    ctor @Deprecated public PagedList.Config.Builder();
+    method @Deprecated public androidx.paging.PagedList.Config build();
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean enablePlaceholders);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(@IntRange(from=1) int initialLoadSizeHint);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setMaxSize(@IntRange(from=2) int maxSize);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setPageSize(@IntRange(from=1) int pageSize);
+    method @Deprecated public androidx.paging.PagedList.Config.Builder setPrefetchDistance(@IntRange(from=0) int prefetchDistance);
+  }
+
+  public final class PagedListConfigKt {
+    method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * androidx.paging.PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = 2147483647);
+  }
+
+  public final class PagedListKt {
+    method @Deprecated public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
+  }
+
+  public final class Pager<Key, Value> {
+    ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, androidx.paging.RemoteMediator<Key,Value>? remoteMediator, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    ctor public Pager(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+    method public kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> getFlow();
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> flow;
+  }
+
+  public final class PagingConfig {
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize, int jumpThreshold);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
+    ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
+    ctor public PagingConfig(int pageSize);
+    field public static final androidx.paging.PagingConfig.Companion Companion;
+    field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+    field public final boolean enablePlaceholders;
+    field public final int initialLoadSize;
+    field public final int jumpThreshold;
+    field public final int maxSize;
+    field public final int pageSize;
+    field public final int prefetchDistance;
+  }
+
+  public static final class PagingConfig.Companion {
+  }
+
+  public final class PagingData<T> {
+    method public static <T> androidx.paging.PagingData<T> empty();
+    method @CheckResult public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+    method @CheckResult public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
+    method @CheckResult public androidx.paging.PagingData<T> insertFooterItem(T item);
+    method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
+    method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+    method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+    field public static final androidx.paging.PagingData.Companion Companion;
+  }
+
+  public static final class PagingData.Companion {
+    method public <T> androidx.paging.PagingData<T> empty();
+    method @CheckResult public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
+  public final class PagingDataKt {
+    method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+  }
+
+  public abstract class PagingSource<Key, Value> {
+    ctor public PagingSource();
+    method public final boolean getInvalid();
+    method public boolean getJumpingSupported();
+    method public boolean getKeyReuseSupported();
+    method @androidx.paging.ExperimentalPagingApi public Key? getRefreshKey(androidx.paging.PagingState<Key,Value> state);
+    method public void invalidate();
+    method public abstract suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+    method public final void registerInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    method public final void unregisterInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+    property public final boolean invalid;
+    property public boolean jumpingSupported;
+    property public boolean keyReuseSupported;
+  }
+
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method @Deprecated public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled);
+    method public Key? getKey();
+  }
+
+  public abstract static sealed class PagingSource.LoadResult<Key, Value> {
+  }
+
+  public static final class PagingSource.LoadResult.Error<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+    ctor public PagingSource.LoadResult.Error(Throwable throwable);
+    method public Throwable component1();
+    method public androidx.paging.PagingSource.LoadResult.Error<Key,Value> copy(Throwable throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class PagingSource.LoadResult.Page<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+    ctor public PagingSource.LoadResult.Page(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, @IntRange(from=null) int itemsBefore, @IntRange(from=null) int itemsAfter);
+    method public java.util.List<Value> component1();
+    method public Key? component2();
+    method public Key? component3();
+    method public int component4();
+    method public int component5();
+    method public androidx.paging.PagingSource.LoadResult.Page<Key,Value> copy(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, int itemsBefore, int itemsAfter);
+    method public java.util.List<Value> getData();
+    method public int getItemsAfter();
+    method public int getItemsBefore();
+    method public Key? getNextKey();
+    method public Key? getPrevKey();
+    field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
+    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
+  }
+
+  public static final class PagingSource.LoadResult.Page.Companion {
+  }
+
+  public final class PagingSourceKt {
+  }
+
+  public final class PagingState<Key, Value> {
+    method public Value? closestItemToPosition(int anchorPosition);
+    method public androidx.paging.PagingSource.LoadResult.Page<Key,Value>? closestPageToPosition(int anchorPosition);
+    method public Value? firstItemOrNull();
+    method public Integer? getAnchorPosition();
+    method public androidx.paging.PagingConfig getConfig();
+    method public java.util.List<androidx.paging.PagingSource.LoadResult.Page<Key,Value>> getPages();
+    method public boolean isEmpty();
+    method public Value? lastItemOrNull();
+  }
+
+  @Deprecated public abstract class PositionalDataSource<T> extends androidx.paging.DataSource<java.lang.Integer,T> {
+    ctor @Deprecated public PositionalDataSource();
+    method @Deprecated public static final int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams params, int totalCount);
+    method @Deprecated public static final int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams params, int initialLoadPosition, int totalCount);
+    method @Deprecated @WorkerThread public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+    method @Deprecated @WorkerThread public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T,V> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(kotlin.jvm.functions.Function1<? super T,? extends V> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>,java.util.List<V>> function);
+    method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends T>,? extends java.util.List<? extends V>> function);
+  }
+
+  @Deprecated public abstract static class PositionalDataSource.LoadInitialCallback<T> {
+    ctor @Deprecated public PositionalDataSource.LoadInitialCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position, int totalCount);
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position);
+  }
+
+  @Deprecated public static class PositionalDataSource.LoadInitialParams {
+    ctor @Deprecated public PositionalDataSource.LoadInitialParams(int requestedStartPosition, int requestedLoadSize, int pageSize, boolean placeholdersEnabled);
+    field @Deprecated public final int pageSize;
+    field @Deprecated public final boolean placeholdersEnabled;
+    field @Deprecated public final int requestedLoadSize;
+    field @Deprecated public final int requestedStartPosition;
+  }
+
+  @Deprecated public abstract static class PositionalDataSource.LoadRangeCallback<T> {
+    ctor @Deprecated public PositionalDataSource.LoadRangeCallback();
+    method @Deprecated public abstract void onResult(java.util.List<? extends T> data);
+  }
+
+  @Deprecated public static class PositionalDataSource.LoadRangeParams {
+    ctor @Deprecated public PositionalDataSource.LoadRangeParams(int startPosition, int loadSize);
+    field @Deprecated public final int loadSize;
+    field @Deprecated public final int startPosition;
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class RemoteMediator<Key, Value> {
+    ctor public RemoteMediator();
+    method public suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> $completion);
+    method public abstract suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+  }
+
+  public enum RemoteMediator.InitializeAction {
+    method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.RemoteMediator.InitializeAction[] values();
+    enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
+    enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
+  }
+
+  public abstract static sealed class RemoteMediator.MediatorResult {
+  }
+
+  public static final class RemoteMediator.MediatorResult.Error extends androidx.paging.RemoteMediator.MediatorResult {
+    ctor public RemoteMediator.MediatorResult.Error(Throwable throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class RemoteMediator.MediatorResult.Success extends androidx.paging.RemoteMediator.MediatorResult {
+    ctor public RemoteMediator.MediatorResult.Success(boolean endOfPaginationReached);
+    method public boolean endOfPaginationReached();
+  }
+
+  public final class SeparatorsKt {
+  }
+
+}
+
+package androidx.paging.multicast {
+
+  public final class ChannelManagerKt {
+  }
+
+}
+
diff --git a/paging/common/api/restricted_current.txt b/paging/common/api/restricted_current.txt
index 351532f..dd27c13 100644
--- a/paging/common/api/restricted_current.txt
+++ b/paging/common/api/restricted_current.txt
@@ -100,7 +100,7 @@
   }
 
   public static final class LoadState.Loading extends androidx.paging.LoadState {
-    field public static final androidx.paging.LoadState.Loading! INSTANCE;
+    field public static final androidx.paging.LoadState.Loading INSTANCE;
   }
 
   public static final class LoadState.NotLoading extends androidx.paging.LoadState {
@@ -119,6 +119,8 @@
   }
 
   public enum LoadType {
+    method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.LoadType[] values();
     enum_constant public static final androidx.paging.LoadType APPEND;
     enum_constant public static final androidx.paging.LoadType PREPEND;
     enum_constant public static final androidx.paging.LoadType REFRESH;
@@ -260,7 +262,7 @@
     ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
     ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
     ctor public PagingConfig(int pageSize);
-    field public static final androidx.paging.PagingConfig.Companion! Companion;
+    field public static final androidx.paging.PagingConfig.Companion Companion;
     field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
     field public final boolean enablePlaceholders;
     field public final int initialLoadSize;
@@ -281,7 +283,7 @@
     method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
     method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
     method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
-    field public static final androidx.paging.PagingData.Companion! Companion;
+    field public static final androidx.paging.PagingData.Companion Companion;
   }
 
   public static final class PagingData.Companion {
@@ -358,7 +360,7 @@
     method public Key? getNextKey();
     method public Key? getPrevKey();
     field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
-    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion! Companion;
+    field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
   }
 
   public static final class PagingSource.LoadResult.Page.Companion {
@@ -422,6 +424,8 @@
   }
 
   public enum RemoteMediator.InitializeAction {
+    method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.paging.RemoteMediator.InitializeAction[] values();
     enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
     enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
   }
diff --git a/paging/common/ktx/api/3.0.0-alpha03.txt b/paging/common/ktx/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/common/ktx/api/3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/common/ktx/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/common/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/common/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/common/ktx/api/restricted_3.0.0-alpha03.txt b/paging/common/ktx/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/common/ktx/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
index 5cc790b..153c632 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
@@ -92,7 +92,8 @@
     @OptIn(ExperimentalCoroutinesApi::class)
     val pageEventFlow: Flow<PageEvent<Value>> = cancelableChannelFlow(pageEventChannelFlowJob) {
         check(pageEventChCollected.compareAndSet(false, true)) {
-            "cannot collect twice from pager"
+            "Attempt to collect twice from pageEventFlow, which is an illegal operation. Did you " +
+                    "forget to call Flow<PagingData<*>>.cachedIn(coroutineScope)?"
         }
 
         // Start collection on pageEventCh, which the rest of this class uses to send PageEvents
diff --git a/paging/guava/api/3.0.0-alpha03.txt b/paging/guava/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..a440d78
--- /dev/null
+++ b/paging/guava/api/3.0.0-alpha03.txt
@@ -0,0 +1,19 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  public abstract class ListenableFuturePagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+    ctor public ListenableFuturePagingSource();
+    method public suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> p, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> $completion);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.PagingSource.LoadResult<Key,Value>> loadFuture(androidx.paging.PagingSource.LoadParams<Key> params);
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class ListenableFutureRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+    ctor public ListenableFutureRemoteMediator();
+    method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.InitializeAction> initializeFuture();
+    method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.MediatorResult> loadFuture(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+  }
+
+}
+
diff --git a/paging/guava/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/guava/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..a440d78
--- /dev/null
+++ b/paging/guava/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,19 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  public abstract class ListenableFuturePagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+    ctor public ListenableFuturePagingSource();
+    method public suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> p, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> $completion);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.PagingSource.LoadResult<Key,Value>> loadFuture(androidx.paging.PagingSource.LoadParams<Key> params);
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class ListenableFutureRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+    ctor public ListenableFutureRemoteMediator();
+    method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.InitializeAction> initializeFuture();
+    method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.MediatorResult> loadFuture(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+  }
+
+}
+
diff --git a/paging/guava/api/res-3.0.0-alpha03.txt b/paging/guava/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/guava/api/res-3.0.0-alpha03.txt
diff --git a/paging/guava/api/restricted_3.0.0-alpha03.txt b/paging/guava/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..a440d78
--- /dev/null
+++ b/paging/guava/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,19 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  public abstract class ListenableFuturePagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+    ctor public ListenableFuturePagingSource();
+    method public suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> p, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> $completion);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.PagingSource.LoadResult<Key,Value>> loadFuture(androidx.paging.PagingSource.LoadParams<Key> params);
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class ListenableFutureRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+    ctor public ListenableFutureRemoteMediator();
+    method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.InitializeAction> initializeFuture();
+    method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.MediatorResult> loadFuture(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+  }
+
+}
+
diff --git a/paging/runtime/api/3.0.0-alpha03.txt b/paging/runtime/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..072f3457
--- /dev/null
+++ b/paging/runtime/api/3.0.0-alpha03.txt
@@ -0,0 +1,133 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  @Deprecated public class AsyncPagedListDiffer<T> {
+    ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter<?> adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback listUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+    method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void addPagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+    method @Deprecated public final void addPagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+    method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+    method @Deprecated public T? getItem(int index);
+    method @Deprecated public int getItemCount();
+    method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void removePagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+    method @Deprecated public final void removePagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+    property public androidx.paging.PagedList<T>? currentList;
+    property public int itemCount;
+  }
+
+  @Deprecated public static interface AsyncPagedListDiffer.PagedListListener<T> {
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+  }
+
+  public final class AsyncPagingDataDiffer<T> {
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback);
+    method @androidx.paging.ExperimentalPagingApi public void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> 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.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public void retry();
+    method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+    property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+    property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+  }
+
+  @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 @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 {
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+  }
+
+  public abstract class LoadStateAdapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor public LoadStateAdapter();
+    method public boolean displayLoadStateAsItem(androidx.paging.LoadState loadState);
+    method public final int getItemCount();
+    method public final int getItemViewType(int position);
+    method public final androidx.paging.LoadState getLoadState();
+    method public int getStateViewType(androidx.paging.LoadState loadState);
+    method public final void onBindViewHolder(VH holder, int position);
+    method public abstract void onBindViewHolder(VH holder, androidx.paging.LoadState loadState);
+    method public final VH onCreateViewHolder(android.view.ViewGroup parent, int viewType);
+    method public abstract VH onCreateViewHolder(android.view.ViewGroup parent, androidx.paging.LoadState loadState);
+    method public final void setLoadState(androidx.paging.LoadState loadState);
+    property public final androidx.paging.LoadState loadState;
+  }
+
+  public final class NullPaddedListDiffHelperKt {
+  }
+
+  @Deprecated public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+    method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+    method @Deprecated protected T? getItem(int position);
+    method @Deprecated public int getItemCount();
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? currentList);
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+    method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+    property public androidx.paging.PagedList<T>? currentList;
+  }
+
+  public abstract class PagingDataAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    method @androidx.paging.ExperimentalPagingApi public final void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public final void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+    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.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public final void retry();
+    method public final suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+    property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+  }
+
+  public final class PagingLiveData {
+    method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, androidx.lifecycle.Lifecycle lifecycle);
+    method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagingData<Value>> getLiveData(androidx.paging.Pager<Key,Value>);
+  }
+
+}
+
diff --git a/paging/runtime/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/runtime/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..072f3457
--- /dev/null
+++ b/paging/runtime/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,133 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  @Deprecated public class AsyncPagedListDiffer<T> {
+    ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter<?> adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback listUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+    method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void addPagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+    method @Deprecated public final void addPagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+    method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+    method @Deprecated public T? getItem(int index);
+    method @Deprecated public int getItemCount();
+    method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void removePagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+    method @Deprecated public final void removePagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+    property public androidx.paging.PagedList<T>? currentList;
+    property public int itemCount;
+  }
+
+  @Deprecated public static interface AsyncPagedListDiffer.PagedListListener<T> {
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+  }
+
+  public final class AsyncPagingDataDiffer<T> {
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback);
+    method @androidx.paging.ExperimentalPagingApi public void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> 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.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public void retry();
+    method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+    property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+    property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+  }
+
+  @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 @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 {
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+  }
+
+  public abstract class LoadStateAdapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor public LoadStateAdapter();
+    method public boolean displayLoadStateAsItem(androidx.paging.LoadState loadState);
+    method public final int getItemCount();
+    method public final int getItemViewType(int position);
+    method public final androidx.paging.LoadState getLoadState();
+    method public int getStateViewType(androidx.paging.LoadState loadState);
+    method public final void onBindViewHolder(VH holder, int position);
+    method public abstract void onBindViewHolder(VH holder, androidx.paging.LoadState loadState);
+    method public final VH onCreateViewHolder(android.view.ViewGroup parent, int viewType);
+    method public abstract VH onCreateViewHolder(android.view.ViewGroup parent, androidx.paging.LoadState loadState);
+    method public final void setLoadState(androidx.paging.LoadState loadState);
+    property public final androidx.paging.LoadState loadState;
+  }
+
+  public final class NullPaddedListDiffHelperKt {
+  }
+
+  @Deprecated public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+    method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+    method @Deprecated protected T? getItem(int position);
+    method @Deprecated public int getItemCount();
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? currentList);
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+    method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+    property public androidx.paging.PagedList<T>? currentList;
+  }
+
+  public abstract class PagingDataAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    method @androidx.paging.ExperimentalPagingApi public final void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public final void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+    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.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public final void retry();
+    method public final suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+    property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+  }
+
+  public final class PagingLiveData {
+    method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, androidx.lifecycle.Lifecycle lifecycle);
+    method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagingData<Value>> getLiveData(androidx.paging.Pager<Key,Value>);
+  }
+
+}
+
diff --git a/paging/runtime/api/res-3.0.0-alpha03.txt b/paging/runtime/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/runtime/api/res-3.0.0-alpha03.txt
diff --git a/paging/runtime/api/restricted_3.0.0-alpha03.txt b/paging/runtime/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..072f3457
--- /dev/null
+++ b/paging/runtime/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,133 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  @Deprecated public class AsyncPagedListDiffer<T> {
+    ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter<?> adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback listUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+    method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void addPagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+    method @Deprecated public final void addPagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+    method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+    method @Deprecated public T? getItem(int index);
+    method @Deprecated public int getItemCount();
+    method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void removePagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+    method @Deprecated public final void removePagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+    property public androidx.paging.PagedList<T>? currentList;
+    property public int itemCount;
+  }
+
+  @Deprecated public static interface AsyncPagedListDiffer.PagedListListener<T> {
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+  }
+
+  public final class AsyncPagingDataDiffer<T> {
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+    ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback);
+    method @androidx.paging.ExperimentalPagingApi public void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> 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.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public void retry();
+    method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+    property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+    property public final int itemCount;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+  }
+
+  @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 @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 {
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+    method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+  }
+
+  public abstract class LoadStateAdapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor public LoadStateAdapter();
+    method public boolean displayLoadStateAsItem(androidx.paging.LoadState loadState);
+    method public final int getItemCount();
+    method public final int getItemViewType(int position);
+    method public final androidx.paging.LoadState getLoadState();
+    method public int getStateViewType(androidx.paging.LoadState loadState);
+    method public final void onBindViewHolder(VH holder, int position);
+    method public abstract void onBindViewHolder(VH holder, androidx.paging.LoadState loadState);
+    method public final VH onCreateViewHolder(android.view.ViewGroup parent, int viewType);
+    method public abstract VH onCreateViewHolder(android.view.ViewGroup parent, androidx.paging.LoadState loadState);
+    method public final void setLoadState(androidx.paging.LoadState loadState);
+    property public final androidx.paging.LoadState loadState;
+  }
+
+  public final class NullPaddedListDiffHelperKt {
+  }
+
+  @Deprecated public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+    method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+    method @Deprecated protected T? getItem(int position);
+    method @Deprecated public int getItemCount();
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? currentList);
+    method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+    method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+    method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+    method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+    property public androidx.paging.PagedList<T>? currentList;
+  }
+
+  public abstract class PagingDataAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+    method @androidx.paging.ExperimentalPagingApi public final void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public final void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+    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.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+    method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+    method public final void retry();
+    method public final suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+    method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+    property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+  }
+
+  public final class PagingLiveData {
+    method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, androidx.lifecycle.Lifecycle lifecycle);
+    method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagingData<Value>> getLiveData(androidx.paging.Pager<Key,Value>);
+  }
+
+}
+
diff --git a/paging/runtime/ktx/api/3.0.0-alpha03.txt b/paging/runtime/ktx/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/runtime/ktx/api/3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/runtime/ktx/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/runtime/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/runtime/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/runtime/ktx/api/res-3.0.0-alpha03.txt b/paging/runtime/ktx/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/runtime/ktx/api/res-3.0.0-alpha03.txt
diff --git a/paging/runtime/ktx/api/restricted_3.0.0-alpha03.txt b/paging/runtime/ktx/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/runtime/ktx/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/rxjava2/api/3.0.0-alpha03.txt b/paging/rxjava2/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..4923f87
--- /dev/null
+++ b/paging/rxjava2/api/3.0.0-alpha03.txt
@@ -0,0 +1,54 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  @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 @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 {
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+  }
+
+}
+
+package androidx.paging.rxjava2 {
+
+  public final class PagingRx {
+    method public static <T> io.reactivex.Observable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Observable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <T> io.reactivex.Flowable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Flowable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagingData<Value>> getFlowable(androidx.paging.Pager<Key,Value>);
+    method public static <Key, Value> io.reactivex.Observable<androidx.paging.PagingData<Value>> getObservable(androidx.paging.Pager<Key,Value>);
+  }
+
+  public abstract class RxPagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+    ctor public RxPagingSource();
+    method public final suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+    method public abstract io.reactivex.Single<androidx.paging.PagingSource.LoadResult<Key,Value>> loadSingle(androidx.paging.PagingSource.LoadParams<Key> params);
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class RxRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+    ctor public RxRemoteMediator();
+    method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+    method public io.reactivex.Single<androidx.paging.RemoteMediator.InitializeAction> initializeSingle();
+    method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+    method public abstract io.reactivex.Single<androidx.paging.RemoteMediator.MediatorResult> loadSingle(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+  }
+
+}
+
diff --git a/paging/rxjava2/api/api_lint.ignore b/paging/rxjava2/api/api_lint.ignore
index 153d977..43bf4f5 100644
--- a/paging/rxjava2/api/api_lint.ignore
+++ b/paging/rxjava2/api/api_lint.ignore
@@ -3,11 +3,3 @@
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.paging.RxPagedListBuilder.buildFlowable(io.reactivex.BackpressureStrategy)
 BuilderSetStyle: androidx.paging.RxPagedListBuilder#buildObservable():
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.paging.RxPagedListBuilder.buildObservable()
-
-
-MissingBuildMethod: androidx.paging.RxPagedListBuilder:
-    androidx.paging.RxPagedListBuilder does not declare a `build()` method, but builder classes are expected to
-
-
-TopLevelBuilder: androidx.paging.RxPagedListBuilder:
-    Builder should be defined as inner class: androidx.paging.RxPagedListBuilder
diff --git a/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..4923f87
--- /dev/null
+++ b/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,54 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  @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 @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 {
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+  }
+
+}
+
+package androidx.paging.rxjava2 {
+
+  public final class PagingRx {
+    method public static <T> io.reactivex.Observable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Observable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <T> io.reactivex.Flowable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Flowable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagingData<Value>> getFlowable(androidx.paging.Pager<Key,Value>);
+    method public static <Key, Value> io.reactivex.Observable<androidx.paging.PagingData<Value>> getObservable(androidx.paging.Pager<Key,Value>);
+  }
+
+  public abstract class RxPagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+    ctor public RxPagingSource();
+    method public final suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+    method public abstract io.reactivex.Single<androidx.paging.PagingSource.LoadResult<Key,Value>> loadSingle(androidx.paging.PagingSource.LoadParams<Key> params);
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class RxRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+    ctor public RxRemoteMediator();
+    method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+    method public io.reactivex.Single<androidx.paging.RemoteMediator.InitializeAction> initializeSingle();
+    method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+    method public abstract io.reactivex.Single<androidx.paging.RemoteMediator.MediatorResult> loadSingle(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+  }
+
+}
+
diff --git a/paging/rxjava2/api/res-3.0.0-alpha03.txt b/paging/rxjava2/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/rxjava2/api/res-3.0.0-alpha03.txt
diff --git a/paging/rxjava2/api/restricted_3.0.0-alpha03.txt b/paging/rxjava2/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..4923f87
--- /dev/null
+++ b/paging/rxjava2/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,54 @@
+// Signature format: 3.0
+package androidx.paging {
+
+  @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 @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 {
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+    method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+  }
+
+}
+
+package androidx.paging.rxjava2 {
+
+  public final class PagingRx {
+    method public static <T> io.reactivex.Observable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Observable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <T> io.reactivex.Flowable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Flowable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+    method public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagingData<Value>> getFlowable(androidx.paging.Pager<Key,Value>);
+    method public static <Key, Value> io.reactivex.Observable<androidx.paging.PagingData<Value>> getObservable(androidx.paging.Pager<Key,Value>);
+  }
+
+  public abstract class RxPagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+    ctor public RxPagingSource();
+    method public final suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+    method public abstract io.reactivex.Single<androidx.paging.PagingSource.LoadResult<Key,Value>> loadSingle(androidx.paging.PagingSource.LoadParams<Key> params);
+  }
+
+  @androidx.paging.ExperimentalPagingApi public abstract class RxRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+    ctor public RxRemoteMediator();
+    method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+    method public io.reactivex.Single<androidx.paging.RemoteMediator.InitializeAction> initializeSingle();
+    method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+    method public abstract io.reactivex.Single<androidx.paging.RemoteMediator.MediatorResult> loadSingle(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+  }
+
+}
+
diff --git a/paging/rxjava2/ktx/api/3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/rxjava2/ktx/api/3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/rxjava2/ktx/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/rxjava2/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/rxjava2/ktx/api/res-3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/rxjava2/ktx/api/res-3.0.0-alpha03.txt
diff --git a/paging/rxjava2/ktx/api/restricted_3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/rxjava2/ktx/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/palette/palette/api/api_lint.ignore b/palette/palette/api/api_lint.ignore
index 162d7eb..85f67cb 100644
--- a/palette/palette/api/api_lint.ignore
+++ b/palette/palette/api/api_lint.ignore
@@ -1,8 +1,6 @@
 // Baseline format: 1.0
 BuilderSetStyle: androidx.palette.graphics.Palette.Builder#generate():
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.generate()
-BuilderSetStyle: androidx.palette.graphics.Palette.Builder#generate(androidx.palette.graphics.Palette.PaletteAsyncListener):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.generate(androidx.palette.graphics.Palette.PaletteAsyncListener)
 BuilderSetStyle: androidx.palette.graphics.Palette.Builder#maximumColorCount(int):
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.maximumColorCount(int)
 BuilderSetStyle: androidx.palette.graphics.Palette.Builder#resizeBitmapArea(int):
diff --git a/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml b/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml
index 96e0fb7..8653650 100644
--- a/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml
+++ b/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml
@@ -23,6 +23,9 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+            <!-- enable profileableByShell for non-intrusive profiling tools -->
+            <!--suppress AndroidElementNotAllowed -->
+            <profileable android:shell="true"/>
             <activity
                     android:name=".RecyclerViewActivity"
                     android:theme="@style/BenchmarkTheme"/>
diff --git a/room/benchmark/src/androidTest/AndroidManifest.xml b/room/benchmark/src/androidTest/AndroidManifest.xml
index aeadd7c..23bc3af 100644
--- a/room/benchmark/src/androidTest/AndroidManifest.xml
+++ b/room/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt b/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
new file mode 100644
index 0000000..fd9c3b2
--- /dev/null
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.solver
+
+import androidx.room.ext.RoomRxJava2TypeNames
+import androidx.room.ext.RxJava2TypeNames
+import androidx.room.processor.ProcessorErrors
+import com.squareup.javapoet.ClassName
+
+internal enum class RxType(
+    val version: RxVersion,
+    val className: ClassName,
+    val factoryMethodName: String? = null,
+    val canBeNull: Boolean = false
+) {
+    RX2_FLOWABLE(
+        version = RxVersion.TWO,
+        className = RxJava2TypeNames.FLOWABLE,
+        factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE),
+    RX2_OBSERVABLE(
+        version = RxVersion.TWO,
+        className = RxJava2TypeNames.OBSERVABLE,
+        factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE),
+    RX2_SINGLE(
+        version = RxVersion.TWO,
+        className = RxJava2TypeNames.SINGLE),
+    RX2_MAYBE(
+        version = RxVersion.TWO,
+        className = RxJava2TypeNames.MAYBE,
+        canBeNull = true),
+    RX2_COMPLETABLE(
+        version = RxVersion.TWO,
+        className = RxJava2TypeNames.COMPLETABLE);
+
+    fun isSingle() = this == RX2_SINGLE
+}
+
+internal enum class RxVersion(
+    val rxRoomClassName: ClassName,
+    val emptyResultExceptionClassName: ClassName,
+    val missingArtifactMessage: String
+) {
+    TWO(
+        rxRoomClassName = RoomRxJava2TypeNames.RX_ROOM,
+        emptyResultExceptionClassName = RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+        missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT),
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 07f17d0..dcb598e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -36,17 +36,14 @@
 import androidx.room.solver.binderprovider.InstantQueryResultBinderProvider
 import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
 import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxFlowableQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxMaybeQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxObservableQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxSingleQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxCallableQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
 import androidx.room.solver.prepared.binder.InstantPreparedQueryResultBinder
 import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
 import androidx.room.solver.prepared.binderprovider.GuavaListenableFuturePreparedQueryResultBinderProvider
 import androidx.room.solver.prepared.binderprovider.InstantPreparedQueryResultBinderProvider
-import androidx.room.solver.prepared.binderprovider.RxCompletablePreparedQueryResultBinderProvider
-import androidx.room.solver.prepared.binderprovider.RxMaybePreparedQueryResultBinderProvider
-import androidx.room.solver.prepared.binderprovider.RxSinglePreparedQueryResultBinderProvider
+import androidx.room.solver.prepared.binderprovider.PreparedQueryResultBinderProvider
+import androidx.room.solver.prepared.binderprovider.RxPreparedQueryResultBinderProvider
 import androidx.room.solver.prepared.result.PreparedQueryResultAdapter
 import androidx.room.solver.query.parameter.ArrayQueryParameterAdapter
 import androidx.room.solver.query.parameter.BasicQueryParameterAdapter
@@ -69,16 +66,14 @@
 import androidx.room.solver.shortcut.binder.InsertMethodBinder
 import androidx.room.solver.shortcut.binder.InstantDeleteOrUpdateMethodBinder
 import androidx.room.solver.shortcut.binder.InstantInsertMethodBinder
+import androidx.room.solver.shortcut.binderprovider.DeleteOrUpdateMethodBinderProvider
 import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureDeleteOrUpdateMethodBinderProvider
 import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureInsertMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.InsertMethodBinderProvider
 import androidx.room.solver.shortcut.binderprovider.InstantDeleteOrUpdateMethodBinderProvider
 import androidx.room.solver.shortcut.binderprovider.InstantInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleInsertMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableDeleteOrUpdateMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableInsertMethodBinderProvider
 import androidx.room.solver.shortcut.result.DeleteOrUpdateMethodAdapter
 import androidx.room.solver.shortcut.result.InsertMethodAdapter
 import androidx.room.solver.types.BoxedBooleanToBoxedIntConverter
@@ -169,44 +164,40 @@
         }
     }
 
-    val queryResultBinderProviders = listOf(
-            CursorQueryResultBinderProvider(context),
-            LiveDataQueryResultBinderProvider(context),
-            GuavaListenableFutureQueryResultBinderProvider(context),
-            RxFlowableQueryResultBinderProvider(context),
-            RxObservableQueryResultBinderProvider(context),
-            RxMaybeQueryResultBinderProvider(context),
-            RxSingleQueryResultBinderProvider(context),
-            DataSourceQueryResultBinderProvider(context),
-            DataSourceFactoryQueryResultBinderProvider(context),
-            PagingSourceQueryResultBinderProvider(context),
-            CoroutineFlowResultBinderProvider(context),
-            InstantQueryResultBinderProvider(context)
-    )
+    val queryResultBinderProviders: List<QueryResultBinderProvider> =
+        mutableListOf<QueryResultBinderProvider>().apply {
+            add(CursorQueryResultBinderProvider(context))
+            add(LiveDataQueryResultBinderProvider(context))
+            add(GuavaListenableFutureQueryResultBinderProvider(context))
+            addAll(RxQueryResultBinderProvider.getAll(context))
+            addAll(RxCallableQueryResultBinderProvider.getAll(context))
+            add(DataSourceQueryResultBinderProvider(context))
+            add(DataSourceFactoryQueryResultBinderProvider(context))
+            add(PagingSourceQueryResultBinderProvider(context))
+            add(CoroutineFlowResultBinderProvider(context))
+            add(InstantQueryResultBinderProvider(context))
+        }
 
-    val preparedQueryResultBinderProviders = listOf(
-            RxSinglePreparedQueryResultBinderProvider(context),
-            RxMaybePreparedQueryResultBinderProvider(context),
-            RxCompletablePreparedQueryResultBinderProvider(context),
-            GuavaListenableFuturePreparedQueryResultBinderProvider(context),
-            InstantPreparedQueryResultBinderProvider(context)
-    )
+    val preparedQueryResultBinderProviders: List<PreparedQueryResultBinderProvider> =
+        mutableListOf<PreparedQueryResultBinderProvider>().apply {
+            addAll(RxPreparedQueryResultBinderProvider.getAll(context))
+            add(GuavaListenableFuturePreparedQueryResultBinderProvider(context))
+            add(InstantPreparedQueryResultBinderProvider(context))
+        }
 
-    val insertBinderProviders = listOf(
-            RxSingleInsertMethodBinderProvider(context),
-            RxMaybeInsertMethodBinderProvider(context),
-            RxCompletableInsertMethodBinderProvider(context),
-            GuavaListenableFutureInsertMethodBinderProvider(context),
-            InstantInsertMethodBinderProvider(context)
-    )
+    val insertBinderProviders: List<InsertMethodBinderProvider> =
+        mutableListOf<InsertMethodBinderProvider>().apply {
+            addAll(RxCallableInsertMethodBinderProvider.getAll(context))
+            add(GuavaListenableFutureInsertMethodBinderProvider(context))
+            add(InstantInsertMethodBinderProvider(context))
+        }
 
-    val deleteOrUpdateBinderProvider = listOf(
-            RxSingleDeleteOrUpdateMethodBinderProvider(context),
-            RxMaybeDeleteOrUpdateMethodBinderProvider(context),
-            RxCompletableDeleteOrUpdateMethodBinderProvider(context),
-            GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(context),
-            InstantDeleteOrUpdateMethodBinderProvider(context)
-    )
+    val deleteOrUpdateBinderProvider: List<DeleteOrUpdateMethodBinderProvider> =
+        mutableListOf<DeleteOrUpdateMethodBinderProvider>().apply {
+            addAll(RxCallableDeleteOrUpdateMethodBinderProvider.getAll(context))
+            add(GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(context))
+            add(InstantDeleteOrUpdateMethodBinderProvider(context))
+        }
 
     // type mirrors that be converted into columns w/o an extra converter
     private val knownColumnTypeMirrors by lazy {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
index 518500e..9cc4717 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
@@ -16,24 +16,22 @@
 
 package androidx.room.solver.binderprovider
 
-import androidx.room.ext.RoomRxJava2TypeNames
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
-import androidx.room.processor.ProcessorErrors
 import androidx.room.solver.QueryResultBinderProvider
+import androidx.room.solver.RxType
 import androidx.room.solver.query.result.QueryResultBinder
 import androidx.room.solver.query.result.RxCallableQueryResultBinder
 import javax.lang.model.type.DeclaredType
 
-sealed class RxCallableQueryResultBinderProvider(
+class RxCallableQueryResultBinderProvider private constructor(
     val context: Context,
-    val rxType: RxCallableQueryResultBinder.RxType
-) :
-    QueryResultBinderProvider {
-    private val hasRxJava2Artifact by lazy {
+    private val rxType: RxType
+) : QueryResultBinderProvider {
+    private val hasRxJavaArtifact by lazy {
         context.processingEnv.elementUtils
-                .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
+            .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
     }
 
     override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
@@ -43,20 +41,21 @@
     }
 
     override fun matches(declared: DeclaredType): Boolean =
-            declared.typeArguments.size == 1 && matchesRxType(declared)
+        declared.typeArguments.size == 1 && matchesRxType(declared)
 
     private fun matchesRxType(declared: DeclaredType): Boolean {
         val erasure = context.processingEnv.typeUtils.erasure(declared)
         val match = erasure.typeName() == rxType.className
-        if (match && !hasRxJava2Artifact) {
-            context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+        if (match && !hasRxJavaArtifact) {
+            context.logger.e(rxType.version.missingArtifactMessage)
         }
         return match
     }
+
+    companion object {
+        fun getAll(context: Context) = listOf(
+            RxType.RX2_SINGLE,
+            RxType.RX2_MAYBE
+        ).map { RxCallableQueryResultBinderProvider(context, it) }
+    }
 }
-
-class RxSingleQueryResultBinderProvider(context: Context) :
-    RxCallableQueryResultBinderProvider(context, RxCallableQueryResultBinder.RxType.SINGLE)
-
-class RxMaybeQueryResultBinderProvider(context: Context) :
-    RxCallableQueryResultBinderProvider(context, RxCallableQueryResultBinder.RxType.MAYBE)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
index 67a9e87..7861ec7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
@@ -16,27 +16,26 @@
 
 package androidx.room.solver.binderprovider
 
-import androidx.room.ext.RoomRxJava2TypeNames
 import androidx.room.processor.Context
-import androidx.room.processor.ProcessorErrors
 import androidx.room.solver.ObservableQueryResultBinderProvider
+import androidx.room.solver.RxType
 import androidx.room.solver.query.result.QueryResultAdapter
 import androidx.room.solver.query.result.QueryResultBinder
 import androidx.room.solver.query.result.RxQueryResultBinder
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
-sealed class RxQueryResultBinderProvider(
+class RxQueryResultBinderProvider private constructor(
     context: Context,
-    private val rxType: RxQueryResultBinder.RxType
+    private val rxType: RxType
 ) : ObservableQueryResultBinderProvider(context) {
     private val typeMirror: TypeMirror? by lazy {
         context.processingEnv.elementUtils
-                .getTypeElement(rxType.className.toString())?.asType()
+            .getTypeElement(rxType.className.toString())?.asType()
     }
-    private val hasRxJava2Artifact by lazy {
+    private val hasRxJavaArtifact by lazy {
         context.processingEnv.elementUtils
-                .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
+            .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
     }
 
     override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
@@ -47,15 +46,15 @@
         tableNames: Set<String>
     ): QueryResultBinder {
         return RxQueryResultBinder(
-                rxType = rxType,
-                typeArg = typeArg,
-                queryTableNames = tableNames,
-                adapter = resultAdapter
+            rxType = rxType,
+            typeArg = typeArg,
+            queryTableNames = tableNames,
+            adapter = resultAdapter
         )
     }
 
     override fun matches(declared: DeclaredType): Boolean =
-            declared.typeArguments.size == 1 && matchesRxType(declared)
+        declared.typeArguments.size == 1 && matchesRxType(declared)
 
     private fun matchesRxType(declared: DeclaredType): Boolean {
         if (typeMirror == null) {
@@ -63,15 +62,16 @@
         }
         val erasure = context.processingEnv.typeUtils.erasure(declared)
         val match = context.processingEnv.typeUtils.isAssignable(typeMirror, erasure)
-        if (match && !hasRxJava2Artifact) {
-            context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+        if (match && !hasRxJavaArtifact) {
+            context.logger.e(rxType.version.missingArtifactMessage)
         }
         return match
     }
-}
 
-class RxFlowableQueryResultBinderProvider(context: Context) :
-    RxQueryResultBinderProvider(context, RxQueryResultBinder.RxType.FLOWABLE)
-
-class RxObservableQueryResultBinderProvider(context: Context) :
-    RxQueryResultBinderProvider(context, RxQueryResultBinder.RxType.OBSERVABLE)
\ No newline at end of file
+    companion object {
+        fun getAll(context: Context) = listOf(
+            RxType.RX2_FLOWABLE,
+            RxType.RX2_OBSERVABLE
+        ).map { RxQueryResultBinderProvider(context, it) }
+    }
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
index 6d12c62..57cef99 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
@@ -17,27 +17,25 @@
 package androidx.room.solver.prepared.binderprovider
 
 import androidx.room.ext.L
-import androidx.room.ext.RoomRxJava2TypeNames
 import androidx.room.ext.RxJava2TypeNames
 import androidx.room.ext.T
 import androidx.room.ext.typeName
 import androidx.room.parser.ParsedQuery
 import androidx.room.processor.Context
-import androidx.room.processor.ProcessorErrors
+import androidx.room.solver.RxType
 import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
 import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
-import com.squareup.javapoet.ClassName
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
-sealed class RxPreparedQueryResultBinderProvider(
+open class RxPreparedQueryResultBinderProvider internal constructor(
     val context: Context,
-    val rxType: RxType
+    private val rxType: RxType
 ) : PreparedQueryResultBinderProvider {
 
-    private val hasRxJava2Artifact by lazy {
+    private val hasRxJavaArtifact by lazy {
         context.processingEnv.elementUtils
-            .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
+            .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
     }
 
     override fun matches(declared: DeclaredType): Boolean =
@@ -49,8 +47,8 @@
     }
 
     override fun provide(declared: DeclaredType, query: ParsedQuery): PreparedQueryResultBinder {
-        if (!hasRxJava2Artifact) {
-            context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+        if (!hasRxJavaArtifact) {
+            context.logger.e(rxType.version.missingArtifactMessage)
         }
         val typeArg = extractTypeArg(declared)
         return createPreparedBinder(
@@ -61,27 +59,21 @@
         }
     }
 
-    abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
+    open fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
 
-    enum class RxType(val className: ClassName) {
-        SINGLE(RxJava2TypeNames.SINGLE),
-        MAYBE(RxJava2TypeNames.MAYBE),
-        COMPLETABLE(RxJava2TypeNames.COMPLETABLE)
+    companion object {
+        fun getAll(context: Context) = listOf(
+            RxPreparedQueryResultBinderProvider(context, RxType.RX2_SINGLE),
+            RxPreparedQueryResultBinderProvider(context, RxType.RX2_MAYBE),
+            RxCompletablePreparedQueryResultBinderProvider(context, RxType.RX2_COMPLETABLE)
+        )
     }
 }
 
-class RxSinglePreparedQueryResultBinderProvider(context: Context) :
-    RxPreparedQueryResultBinderProvider(context, RxType.SINGLE) {
-    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxMaybePreparedQueryResultBinderProvider(context: Context) :
-    RxPreparedQueryResultBinderProvider(context, RxType.MAYBE) {
-    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxCompletablePreparedQueryResultBinderProvider(context: Context) :
-    RxPreparedQueryResultBinderProvider(context, RxType.COMPLETABLE) {
+private class RxCompletablePreparedQueryResultBinderProvider(
+    context: Context,
+    rxType: RxType
+) : RxPreparedQueryResultBinderProvider(context, rxType) {
 
     private val completableType: TypeMirror? by lazy {
         context.processingEnv.elementUtils
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
index d42748a..d1eee32 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -17,17 +17,15 @@
 package androidx.room.solver.query.result
 
 import androidx.room.ext.AndroidTypeNames
+import androidx.room.ext.CallableTypeSpecBuilder
 import androidx.room.ext.L
 import androidx.room.ext.N
-import androidx.room.ext.RoomRxJava2TypeNames
 import androidx.room.ext.RoomTypeNames
-import androidx.room.ext.RxJava2TypeNames
 import androidx.room.ext.S
 import androidx.room.ext.T
-import androidx.room.ext.CallableTypeSpecBuilder
 import androidx.room.ext.typeName
 import androidx.room.solver.CodeGenScope
-import com.squareup.javapoet.ClassName
+import androidx.room.solver.RxType
 import com.squareup.javapoet.FieldSpec
 import com.squareup.javapoet.MethodSpec
 import javax.lang.model.element.Modifier
@@ -36,7 +34,7 @@
 /**
  * Generic Result binder for Rx classes that accept a callable.
  */
-class RxCallableQueryResultBinder(
+internal class RxCallableQueryResultBinder(
     private val rxType: RxType,
     val typeArg: TypeMirror,
     adapter: QueryResultAdapter?
@@ -60,8 +58,8 @@
             }
         }.build()
         scope.builder().apply {
-            if (rxType == RxType.SINGLE) {
-                addStatement("return $T.createSingle($L)", RoomRxJava2TypeNames.RX_ROOM, callable)
+            if (rxType.isSingle()) {
+                addStatement("return $T.createSingle($L)", rxType.version.rxRoomClassName, callable)
             } else {
                 addStatement("return $T.fromCallable($L)", rxType.className, callable)
             }
@@ -98,7 +96,7 @@
             if (!rxType.canBeNull) {
                 beginControlFlow("if($L == null)", outVar).apply {
                     addStatement("throw new $T($S + $L.getSql())",
-                            RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+                            rxType.version.emptyResultExceptionClassName,
                             "Query returned empty result set: ",
                             roomSQLiteQueryVar)
                 }
@@ -121,9 +119,4 @@
             addStatement("$L.release()", roomSQLiteQueryVar)
         }.build()
     }
-
-    enum class RxType(val className: ClassName, val canBeNull: Boolean) {
-        SINGLE(RxJava2TypeNames.SINGLE, canBeNull = false),
-        MAYBE(RxJava2TypeNames.MAYBE, canBeNull = true);
-    }
 }
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
index 4bdc734..109df19 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
@@ -16,23 +16,21 @@
 
 package androidx.room.solver.query.result
 
+import androidx.room.ext.CallableTypeSpecBuilder
 import androidx.room.ext.L
 import androidx.room.ext.N
-import androidx.room.ext.RoomRxJava2TypeNames
-import androidx.room.ext.RxJava2TypeNames
 import androidx.room.ext.T
-import androidx.room.ext.CallableTypeSpecBuilder
 import androidx.room.ext.arrayTypeName
 import androidx.room.ext.typeName
 import androidx.room.solver.CodeGenScope
-import com.squareup.javapoet.ClassName
+import androidx.room.solver.RxType
 import com.squareup.javapoet.FieldSpec
 import javax.lang.model.type.TypeMirror
 
 /**
  * Binds the result as an RxJava2 Flowable, Publisher and Observable.
  */
-class RxQueryResultBinder(
+internal class RxQueryResultBinder(
     private val rxType: RxType,
     val typeArg: TypeMirror,
     val queryTableNames: Set<String>,
@@ -60,8 +58,8 @@
         scope.builder().apply {
             val tableNamesList = queryTableNames.joinToString(",") { "\"$it\"" }
             addStatement("return $T.$N($N, $L, new $T{$L}, $L)",
-                RoomRxJava2TypeNames.RX_ROOM,
-                rxType.methodName,
+                rxType.version.rxRoomClassName,
+                rxType.factoryMethodName,
                 dbField,
                 if (inTransaction) "true" else "false",
                 String::class.arrayTypeName(),
@@ -69,9 +67,4 @@
                 callableImpl)
         }
     }
-
-    enum class RxType(val className: ClassName, val methodName: String) {
-        FLOWABLE(RxJava2TypeNames.FLOWABLE, RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE),
-        OBSERVABLE(RxJava2TypeNames.OBSERVABLE, RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE)
-    }
 }
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
index 0f04bda..67bb1f8 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
@@ -21,16 +21,16 @@
 import androidx.room.ext.T
 import androidx.room.ext.typeName
 import androidx.room.processor.Context
+import androidx.room.solver.RxType
 import androidx.room.solver.shortcut.binder.CallableDeleteOrUpdateMethodBinder.Companion.createDeleteOrUpdateBinder
 import androidx.room.solver.shortcut.binder.DeleteOrUpdateMethodBinder
-import com.squareup.javapoet.ClassName
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
 /**
  * Provider for Rx Callable binders.
  */
-sealed class RxCallableDeleteOrUpdateMethodBinderProvider(
+open class RxCallableDeleteOrUpdateMethodBinderProvider internal constructor(
     val context: Context,
     private val rxType: RxType
 ) : DeleteOrUpdateMethodBinderProvider {
@@ -39,7 +39,7 @@
      * [Single] and [Maybe] are generics but [Completable] is not so each implementation of this
      * class needs to define how to extract the type argument.
      */
-    abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
+    open fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
 
     override fun matches(declared: DeclaredType): Boolean =
             declared.typeArguments.size == 1 && matchesRxType(declared)
@@ -57,30 +57,19 @@
         }
     }
 
-    /**
-     * Supported types for delete and update
-     */
-    enum class RxType(val className: ClassName) {
-        SINGLE(RxJava2TypeNames.SINGLE),
-        MAYBE(RxJava2TypeNames.MAYBE),
-        COMPLETABLE(RxJava2TypeNames.COMPLETABLE)
+    companion object {
+        fun getAll(context: Context) = listOf(
+            RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.RX2_SINGLE),
+            RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.RX2_MAYBE),
+            RxCompletableDeleteOrUpdateMethodBinderProvider(context, RxType.RX2_COMPLETABLE)
+        )
     }
 }
 
-class RxSingleDeleteOrUpdateMethodBinderProvider(context: Context) :
-    RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.SINGLE) {
-
-    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxMaybeDeleteOrUpdateMethodBinderProvider(context: Context) :
-    RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.MAYBE) {
-
-    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxCompletableDeleteOrUpdateMethodBinderProvider(context: Context) :
-    RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.COMPLETABLE) {
+private class RxCompletableDeleteOrUpdateMethodBinderProvider(
+    context: Context,
+    rxType: RxType
+) : RxCallableDeleteOrUpdateMethodBinderProvider(context, rxType) {
 
     private val completableTypeMirror: TypeMirror? by lazy {
         context.processingEnv.elementUtils
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
index c207d18..14c2ead 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
@@ -17,21 +17,20 @@
 package androidx.room.solver.shortcut.binderprovider
 
 import androidx.room.ext.L
-import androidx.room.ext.RxJava2TypeNames
 import androidx.room.ext.T
 import androidx.room.ext.typeName
 import androidx.room.processor.Context
+import androidx.room.solver.RxType
 import androidx.room.solver.shortcut.binder.CallableInsertMethodBinder.Companion.createInsertBinder
 import androidx.room.solver.shortcut.binder.InsertMethodBinder
 import androidx.room.vo.ShortcutQueryParameter
-import com.squareup.javapoet.ClassName
 import javax.lang.model.type.DeclaredType
 import javax.lang.model.type.TypeMirror
 
 /**
  * Provider for Rx Callable binders.
  */
-sealed class RxCallableInsertMethodBinderProvider(
+open class RxCallableInsertMethodBinderProvider internal constructor(
     val context: Context,
     private val rxType: RxType
 ) : InsertMethodBinderProvider {
@@ -40,7 +39,7 @@
      * [Single] and [Maybe] are generics but [Completable] is not so each implementation of this
      * class needs to define how to extract the type argument.
      */
-    abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
+    open fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
 
     override fun matches(declared: DeclaredType): Boolean =
             declared.typeArguments.size == 1 && matchesRxType(declared)
@@ -61,35 +60,23 @@
         }
     }
 
-    /**
-     * Supported types for insert
-     */
-    enum class RxType(val className: ClassName) {
-        SINGLE(RxJava2TypeNames.SINGLE),
-        MAYBE(RxJava2TypeNames.MAYBE),
-        COMPLETABLE(RxJava2TypeNames.COMPLETABLE)
+    companion object {
+        fun getAll(context: Context) = listOf(
+            RxCallableInsertMethodBinderProvider(context, RxType.RX2_SINGLE),
+            RxCallableInsertMethodBinderProvider(context, RxType.RX2_MAYBE),
+            RxCompletableInsertMethodBinderProvider(context, RxType.RX2_COMPLETABLE)
+        )
     }
 }
 
-class RxSingleInsertMethodBinderProvider(context: Context) :
-    RxCallableInsertMethodBinderProvider(context, RxType.SINGLE) {
-
-    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxMaybeInsertMethodBinderProvider(context: Context) :
-    RxCallableInsertMethodBinderProvider(context, RxType.MAYBE) {
-
-    override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxCompletableInsertMethodBinderProvider(context: Context) :
-    RxCallableInsertMethodBinderProvider(context,
-        RxType.COMPLETABLE) {
+private class RxCompletableInsertMethodBinderProvider(
+    context: Context,
+    rxType: RxType
+) : RxCallableInsertMethodBinderProvider(context, rxType) {
 
     private val completableTypeMirror: TypeMirror? by lazy {
         context.processingEnv.elementUtils
-                .getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())?.asType()
+                .getTypeElement(rxType.className.toString())?.asType()
     }
 
     /**
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index ce30049..6c79762 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -36,16 +36,11 @@
 import androidx.room.solver.binderprovider.DataSourceQueryResultBinderProvider
 import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
 import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxFlowableQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxObservableQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
 import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureDeleteOrUpdateMethodBinderProvider
 import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleInsertMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableDeleteOrUpdateMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableInsertMethodBinderProvider
 import androidx.room.solver.types.CompositeAdapter
 import androidx.room.solver.types.TypeConverter
 import androidx.room.testing.TestInvocation
@@ -242,8 +237,10 @@
             val publisherElement = invocation.processingEnv.elementUtils
                     .getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
             assertThat(publisherElement, notNullValue())
-            assertThat(RxFlowableQueryResultBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(publisherElement.asType())), `is`(true))
+            assertThat(
+                RxQueryResultBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(publisherElement.asType()))
+                }, `is`(true))
         }.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
     }
 
@@ -254,8 +251,10 @@
             val publisher = invocation.processingEnv.elementUtils
                     .getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
             assertThat(publisher, notNullValue())
-            assertThat(RxFlowableQueryResultBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(publisher.asType())), `is`(true))
+            assertThat(
+                RxQueryResultBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(publisher.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -266,8 +265,10 @@
             val flowable = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.FLOWABLE.toString())
             assertThat(flowable, notNullValue())
-            assertThat(RxFlowableQueryResultBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(flowable.asType())), `is`(true))
+            assertThat(
+                RxQueryResultBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(flowable.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -278,8 +279,10 @@
             val observable = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.OBSERVABLE.toString())
             assertThat(observable, notNullValue())
-            assertThat(RxObservableQueryResultBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(observable.asType())), `is`(true))
+            assertThat(
+                RxQueryResultBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(observable.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -290,8 +293,10 @@
             val single = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.SINGLE.toString())
             assertThat(single, notNullValue())
-            assertThat(RxSingleInsertMethodBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(single.asType())), `is`(true))
+            assertThat(
+                RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(single.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -302,8 +307,10 @@
             val maybe = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.MAYBE.toString())
             assertThat(maybe, notNullValue())
-            assertThat(RxMaybeInsertMethodBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(maybe.asType())), `is`(true))
+            assertThat(
+                RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(maybe.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -314,8 +321,10 @@
             val completable = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())
             assertThat(completable, notNullValue())
-            assertThat(RxCompletableInsertMethodBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(completable.asType())), `is`(true))
+            assertThat(
+                RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(completable.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -338,8 +347,10 @@
             val single = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.SINGLE.toString())
             assertThat(single, notNullValue())
-            assertThat(RxSingleDeleteOrUpdateMethodBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(single.asType())), `is`(true))
+            assertThat(
+                RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(single.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -350,8 +361,10 @@
             val maybe = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.MAYBE.toString())
             assertThat(maybe, notNullValue())
-            assertThat(RxMaybeDeleteOrUpdateMethodBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(maybe.asType())), `is`(true))
+            assertThat(
+                RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(maybe.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
@@ -362,8 +375,10 @@
             val completable = invocation.processingEnv.elementUtils
                     .getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())
             assertThat(completable, notNullValue())
-            assertThat(RxCompletableDeleteOrUpdateMethodBinderProvider(invocation.context).matches(
-                    MoreTypes.asDeclared(completable.asType())), `is`(true))
+            assertThat(
+                RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
+                    it.matches(MoreTypes.asDeclared(completable.asType()))
+                }, `is`(true))
         }.compilesWithoutError()
     }
 
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index f1cac00..a664d56 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -97,6 +97,7 @@
     androidTestImplementation(projectOrArtifact(":paging:paging-runtime"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime-testing"))
+    androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-livedata"))
 
     // FINDBUGS dependency resolves an app/testapp version conflict.
     androidTestImplementation(FINDBUGS)
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
index de24eaa..b46e492 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
@@ -25,7 +25,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.content.Intent;
 import android.os.Build;
 import android.os.SystemClock;
 
@@ -57,6 +56,7 @@
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestName;
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
@@ -72,6 +72,9 @@
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
 public class MultiInstanceInvalidationTest {
 
+    @Rule
+    public TestName testName = new TestName();
+
     private static final Customer CUSTOMER_1 = new Customer();
     private static final Customer CUSTOMER_2 = new Customer();
 
@@ -89,6 +92,8 @@
 
     private ISampleDatabaseService mService;
 
+    private String mDatabaseName;
+
     private final ArrayList<RoomDatabase> mDatabases = new ArrayList<>();
     private final SimpleArrayMap<LiveData<List<Customer>>, Observer<List<Customer>>> mObservers =
             new SimpleArrayMap<>();
@@ -96,7 +101,10 @@
     @Before
     public void setUp() {
         final Context context = ApplicationProvider.getApplicationContext();
-        context.deleteDatabase(SampleDatabaseService.DATABASE_NAME);
+        // use a separate database file for each test because we are not fully capable of closing
+        // and deleting a database connection in a multi-process setup
+        mDatabaseName = "multi-process-" + testName.getMethodName() + ".db";
+        context.deleteDatabase(mDatabaseName);
     }
 
     @After
@@ -339,7 +347,7 @@
     private long measure(boolean multiInstanceInvalidation, boolean bulk,
             List<Customer> customers) {
         final Context context = ApplicationProvider.getApplicationContext();
-        context.deleteDatabase(SampleDatabaseService.DATABASE_NAME);
+        context.deleteDatabase(mDatabaseName);
         final SampleDatabase db = openDatabase(multiInstanceInvalidation);
         final CustomerDao dao = db.getCustomerDao();
         final InvalidationTracker.Observer observer = new InvalidationTracker.Observer("Customer") {
@@ -373,8 +381,7 @@
     private SampleDatabase openDatabase(boolean multiInstanceInvalidation) {
         final Context context = ApplicationProvider.getApplicationContext();
         final RoomDatabase.Builder<SampleDatabase> builder = Room
-                .databaseBuilder(context, SampleDatabase.class,
-                        SampleDatabaseService.DATABASE_NAME);
+                .databaseBuilder(context, SampleDatabase.class, mDatabaseName);
         if (multiInstanceInvalidation) {
             builder.enableMultiInstanceInvalidation();
         }
@@ -386,8 +393,7 @@
     private SampleFtsDatabase openFtsDatabase(boolean multiInstanceInvalidation) {
         final Context context = ApplicationProvider.getApplicationContext();
         final RoomDatabase.Builder<SampleFtsDatabase> builder = Room
-                .databaseBuilder(context, SampleFtsDatabase.class,
-                        SampleDatabaseService.DATABASE_NAME);
+                .databaseBuilder(context, SampleFtsDatabase.class, mDatabaseName);
         if (multiInstanceInvalidation) {
             builder.enableMultiInstanceInvalidation();
         }
@@ -399,7 +405,10 @@
     private void bindTestService() throws TimeoutException {
         final Context context = ApplicationProvider.getApplicationContext();
         mService = ISampleDatabaseService.Stub.asInterface(
-                serviceRule.bindService(new Intent(context, SampleDatabaseService.class)));
+                serviceRule.bindService(SampleDatabaseService.intentFor(
+                        context,
+                        mDatabaseName
+                )));
     }
 
     private CountDownLatch prepareTableObserver(SampleDatabase db) {
diff --git a/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java b/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java
index 8df5ecd..baafa36 100644
--- a/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java
+++ b/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java
@@ -17,6 +17,7 @@
 package androidx.room.integration.testapp;
 
 import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
 import android.os.IBinder;
@@ -39,7 +40,7 @@
  */
 public class SampleDatabaseService extends Service {
 
-    public static final String DATABASE_NAME = "multi-process.db";
+    private static final String DATABASE_NAME_PARAM = "db-name";
 
     private final ISampleDatabaseService.Stub mBinder = new ISampleDatabaseService.Stub() {
 
@@ -87,14 +88,39 @@
     @Override
     public void onCreate() {
         super.onCreate();
-        mDatabase = Room.databaseBuilder(this, SampleDatabase.class, DATABASE_NAME)
-                .enableMultiInstanceInvalidation()
-                .build();
+    }
+
+    /**
+     * Creates the test service for the given database name
+     * @param context The context to creat the intent
+     * @param databaseName The database name to be used
+     * @return A new intent that can be used to connect to this service
+     */
+    public static Intent intentFor(Context context, String databaseName) {
+        Intent intent = new Intent(context, SampleDatabaseService.class);
+        intent.putExtra(DATABASE_NAME_PARAM, databaseName);
+        return intent;
     }
 
     @Nullable
     @Override
     public IBinder onBind(Intent intent) {
+        String databaseName = intent.getStringExtra(DATABASE_NAME_PARAM);
+        if (databaseName == null) {
+            throw new IllegalArgumentException("must pass database name in the intent");
+        }
+        if (mDatabase != null) {
+            throw new IllegalStateException("Cannot re-use the same service for different tests");
+        }
+        mDatabase = Room.databaseBuilder(this, SampleDatabase.class, databaseName)
+                .enableMultiInstanceInvalidation()
+                .build();
         return mBinder;
     }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        mDatabase.close();
+        return super.onUnbind(intent);
+    }
 }
diff --git a/room/ktx/api/restricted_2.3.0-alpha02.txt b/room/ktx/api/restricted_2.3.0-alpha02.txt
index cc27399..371c63c 100644
--- a/room/ktx/api/restricted_2.3.0-alpha02.txt
+++ b/room/ktx/api/restricted_2.3.0-alpha02.txt
@@ -5,7 +5,7 @@
     method public static <R> kotlinx.coroutines.flow.Flow<R> createFlow(androidx.room.RoomDatabase db, boolean inTransaction, String![] tableNames, java.util.concurrent.Callable<R> callable);
     method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, java.util.concurrent.Callable<R> inTransaction, kotlin.coroutines.Continuation<? super R> callable);
     method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, android.os.CancellationSignal inTransaction, java.util.concurrent.Callable<R> cancellationSignal, kotlin.coroutines.Continuation<? super R> callable);
-    field public static final androidx.room.CoroutinesRoom.Companion! Companion;
+    field public static final androidx.room.CoroutinesRoom.Companion Companion;
   }
 
   public static final class CoroutinesRoom.Companion {
diff --git a/room/ktx/api/restricted_current.txt b/room/ktx/api/restricted_current.txt
index cc27399..371c63c 100644
--- a/room/ktx/api/restricted_current.txt
+++ b/room/ktx/api/restricted_current.txt
@@ -5,7 +5,7 @@
     method public static <R> kotlinx.coroutines.flow.Flow<R> createFlow(androidx.room.RoomDatabase db, boolean inTransaction, String![] tableNames, java.util.concurrent.Callable<R> callable);
     method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, java.util.concurrent.Callable<R> inTransaction, kotlin.coroutines.Continuation<? super R> callable);
     method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, android.os.CancellationSignal inTransaction, java.util.concurrent.Callable<R> cancellationSignal, kotlin.coroutines.Continuation<? super R> callable);
-    field public static final androidx.room.CoroutinesRoom.Companion! Companion;
+    field public static final androidx.room.CoroutinesRoom.Companion Companion;
   }
 
   public static final class CoroutinesRoom.Companion {
diff --git a/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java b/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java
index 3dbb8e0..c8a7b5d 100644
--- a/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java
+++ b/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java
@@ -138,22 +138,6 @@
         }
     };
 
-    private final Runnable mTearDownRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mInvalidationTracker.removeObserver(mObserver);
-            try {
-                final IMultiInstanceInvalidationService service = mService;
-                if (service != null) {
-                    service.unregisterCallback(mCallback, mClientId);
-                }
-            } catch (RemoteException e) {
-                Log.w(Room.LOG_TAG, "Cannot unregister multi-instance invalidation callback", e);
-            }
-            mAppContext.unbindService(mServiceConnection);
-        }
-    };
-
     /**
      * @param context             The Context to be used for binding
      *                            {@link IMultiInstanceInvalidationService}.
@@ -196,7 +180,16 @@
 
     void stop() {
         if (mStopped.compareAndSet(false, true)) {
-            mExecutor.execute(mTearDownRunnable);
+            mInvalidationTracker.removeObserver(mObserver);
+            try {
+                final IMultiInstanceInvalidationService service = mService;
+                if (service != null) {
+                    service.unregisterCallback(mCallback, mClientId);
+                }
+            } catch (RemoteException e) {
+                Log.w(Room.LOG_TAG, "Cannot unregister multi-instance invalidation callback", e);
+            }
+            mAppContext.unbindService(mServiceConnection);
         }
     }
 }
diff --git a/samples/Support7Demos/OWNERS b/samples/Support7Demos/OWNERS
index 2f5d227..526fcca 100644
--- a/samples/Support7Demos/OWNERS
+++ b/samples/Support7Demos/OWNERS
@@ -1,6 +1,7 @@
[email protected]
[email protected]
[email protected]
[email protected]
 [email protected]
[email protected]
 [email protected]
[email protected]
\ No newline at end of file
[email protected]
[email protected]
[email protected]
diff --git a/security/crypto/api/api_lint.ignore b/security/crypto/api/api_lint.ignore
index b3ea816..0b681f2 100644
--- a/security/crypto/api/api_lint.ignore
+++ b/security/crypto/api/api_lint.ignore
@@ -9,7 +9,3 @@
     Listener methods should be named add/remove; was registerOnSharedPreferenceChangeListener
 RegistrationName: androidx.security.crypto.EncryptedSharedPreferences#unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener):
     Listener methods should be named add/remove; was unregisterOnSharedPreferenceChangeListener
-
-
-StreamFiles: androidx.security.crypto.EncryptedFile.Builder#Builder(java.io.File, android.content.Context, String, androidx.security.crypto.EncryptedFile.FileEncryptionScheme):
-    Methods accepting `File` should also accept `FileDescriptor` or streams: constructor androidx.security.crypto.EncryptedFile.Builder(java.io.File,android.content.Context,String,androidx.security.crypto.EncryptedFile.FileEncryptionScheme)
diff --git a/serialization/serialization-annotation/api/1.0.0-alpha01.txt b/serialization/serialization-annotation/api/1.0.0-alpha01.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/1.0.0-alpha01.txt
+++ b/serialization/serialization-annotation/api/1.0.0-alpha01.txt
@@ -23,6 +23,8 @@
   }
 
   public enum ProtoEncoding {
+    method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.serialization.ProtoEncoding[] values();
     enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/current.txt b/serialization/serialization-annotation/api/current.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/current.txt
+++ b/serialization/serialization-annotation/api/current.txt
@@ -23,6 +23,8 @@
   }
 
   public enum ProtoEncoding {
+    method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.serialization.ProtoEncoding[] values();
     enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt b/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -23,6 +23,8 @@
   }
 
   public enum ProtoEncoding {
+    method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.serialization.ProtoEncoding[] values();
     enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/public_plus_experimental_current.txt b/serialization/serialization-annotation/api/public_plus_experimental_current.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/public_plus_experimental_current.txt
+++ b/serialization/serialization-annotation/api/public_plus_experimental_current.txt
@@ -23,6 +23,8 @@
   }
 
   public enum ProtoEncoding {
+    method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.serialization.ProtoEncoding[] values();
     enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt b/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt
+++ b/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt
@@ -23,6 +23,8 @@
   }
 
   public enum ProtoEncoding {
+    method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.serialization.ProtoEncoding[] values();
     enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/restricted_current.txt b/serialization/serialization-annotation/api/restricted_current.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/restricted_current.txt
+++ b/serialization/serialization-annotation/api/restricted_current.txt
@@ -23,6 +23,8 @@
   }
 
   public enum ProtoEncoding {
+    method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.serialization.ProtoEncoding[] values();
     enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
     enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/slices/benchmark/src/androidTest/AndroidManifest.xml b/slices/benchmark/src/androidTest/AndroidManifest.xml
index 5fd3108..8e2298b 100644
--- a/slices/benchmark/src/androidTest/AndroidManifest.xml
+++ b/slices/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
     <application
             android:debuggable="false"
             tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
diff --git a/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java b/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java
index 4ab5626..2e1323e 100644
--- a/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java
+++ b/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java
@@ -87,10 +87,10 @@
 
     private class SliceListenerImpl {
 
-        Uri mUri;
+        final Uri mUri;
         final Executor mExecutor;
         final SliceCallback mCallback;
-        private boolean mPinned;
+        boolean mPinned;
 
         SliceListenerImpl(Uri uri, Executor executor, SliceCallback callback) {
             mUri = uri;
@@ -119,14 +119,24 @@
             }
         }
 
+        @SuppressWarnings("deprecation") /* AsyncTask */
         void stopListening() {
             mContext.getContentResolver().unregisterContentObserver(mObserver);
             if (mPinned) {
-                unpinSlice(mUri);
-                mPinned = false;
+                mHandler.post(() -> android.os.AsyncTask.execute(mUnpinSlice));
             }
         }
 
+        private final Runnable mUnpinSlice = new Runnable() {
+            @Override
+            public void run() {
+                if (mPinned) {
+                    unpinSlice(mUri);
+                    mPinned = false;
+                }
+            }
+        };
+
         final Runnable mUpdateSlice = new Runnable() {
             @Override
             public void run() {
@@ -141,8 +151,9 @@
             }
         };
 
-        private final ContentObserver mObserver = new ContentObserver(
-                new Handler(Looper.getMainLooper())) {
+        private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+        private final ContentObserver mObserver = new ContentObserver(mHandler) {
             @Override
             @SuppressWarnings("deprecation") /* AsyncTask */
             public void onChange(boolean selfChange) {
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 8bd56f8..05055df 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
@@ -50,6 +50,8 @@
     private int mProgressBarStartPadding;
     private int mProgressBarEndPadding;
     private int mIconSize;
+    private boolean mDisableRecyclerViewItemAnimator;
+    private int mImageSize;
 
     public RowStyle(Context context, int resId) {
         TypedArray a = context.getTheme().obtainStyledAttributes(resId, R.styleable.RowStyle);
@@ -90,6 +92,10 @@
                     R.styleable.RowStyle_progressBarEndPadding, UNBOUNDED);
             mIconSize = (int) a.getDimension(
                     R.styleable.RowStyle_iconSize, UNBOUNDED);
+            mDisableRecyclerViewItemAnimator = a.getBoolean(
+                    R.styleable.RowStyle_disableRecyclerViewItemAnimator, false);
+            mImageSize = (int) a.getDimension(
+                    R.styleable.RowStyle_imageSize, UNBOUNDED);
         } finally {
             a.recycle();
         }
@@ -166,4 +172,12 @@
     public int getIconSize() {
         return mIconSize;
     }
+
+    public boolean getDisableRecyclerViewItemAnimator() {
+        return mDisableRecyclerViewItemAnimator;
+    }
+
+    public int getImageSize() {
+        return mImageSize;
+    }
 }
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 5e4a0b2..be3932d 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowView.java
@@ -105,6 +105,8 @@
 
     private static final String TAG = "RowView";
 
+    private static final int HEIGHT_UNBOUND = -1;
+
     // The number of items that fit on the right hand side of a small slice
     // TODO: this should be based on available width
     private static final int MAX_END_ITEMS = 3;
@@ -176,6 +178,7 @@
 
     private int mImageSize;
     private int mIconSize;
+    private int mStyleRowHeight = HEIGHT_UNBOUND;
     // How big mRangeBar wants to be.
     private int mMeasuredRangeHeight;
 
@@ -848,7 +851,7 @@
      */
     private void addAction(final SliceActionImpl actionContent, int color, ViewGroup container,
                            boolean isStart) {
-        SliceActionView sav = new SliceActionView(getContext());
+        SliceActionView sav = new SliceActionView(getContext(), mSliceStyle);
         container.addView(sav);
         if (container.getVisibility() == GONE) {
             container.setVisibility(VISIBLE);
@@ -916,16 +919,25 @@
             } else {
                 container.addView(iv);
             }
+            if (mSliceStyle != null) {
+                mStyleRowHeight = mSliceStyle.getRowMinHeight();
+                if (mSliceStyle.getRowStyle() != null) {
+                    int styleIconSize = mSliceStyle.getRowStyle().getIconSize();
+                    mIconSize = styleIconSize > 0 ? styleIconSize : mIconSize;
+                    int styleImageSize = mSliceStyle.getRowStyle().getImageSize();
+                    mImageSize = styleImageSize > 0 ? styleImageSize : mImageSize;
+                }
+            }
             LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) iv.getLayoutParams();
             lp.width = useIntrinsicSize ? Math.round(d.getIntrinsicWidth() / density) : mImageSize;
             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 = 0;
+            if (isIcon) {
+                p = mStyleRowHeight == HEIGHT_UNBOUND
+                    ? mIconSize / 2 : (mStyleRowHeight - mIconSize) / 2;
             }
-            int p = isIcon ? mIconSize / 2 : 0;
             iv.setPadding(p, p, p, p);
             addedView = iv;
         } else if (timeStamp != null) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java b/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java
index 011a129..b2700f5 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java
@@ -58,6 +58,8 @@
         CompoundButton.OnCheckedChangeListener {
     private static final String TAG = "SliceActionView";
 
+    private static final int HEIGHT_UNBOUND = -1;
+
     static final int[] CHECKED_STATE_SET = {
             android.R.attr.state_checked
     };
@@ -76,12 +78,20 @@
 
     private int mIconSize;
     private int mImageSize;
+    private int mStyleRowHeight = HEIGHT_UNBOUND;
 
-    public SliceActionView(Context context) {
+    public SliceActionView(Context context, SliceStyle style) {
         super(context);
         Resources res = getContext().getResources();
         mIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_icon_size);
         mImageSize = res.getDimensionPixelSize(R.dimen.abc_slice_small_image_size);
+        if (style != null) {
+            mStyleRowHeight = style.getRowMinHeight();
+            if (style.getRowStyle() != null) {
+                mIconSize = style.getRowStyle().getIconSize();
+                mImageSize = style.getRowStyle().getImageSize();
+            }
+        }
     }
 
     /**
@@ -164,7 +174,11 @@
             lp.width = mImageSize;
             lp.height = mImageSize;
             mActionView.setLayoutParams(lp);
-            int p = action.getImageMode() == ICON_IMAGE ? mIconSize / 2 : 0;
+            int p = 0;
+            if (action.getImageMode() == ICON_IMAGE) {
+                p = mStyleRowHeight == HEIGHT_UNBOUND
+                    ? mIconSize / 2 : (mStyleRowHeight - mIconSize) / 2;
+            }
             mActionView.setPadding(p, p, p, p);
             int touchFeedbackAttr = android.R.attr.selectableItemBackground;
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -224,7 +238,7 @@
     }
 
     @Override
-    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+    public void onCheckedChanged(@Nullable CompoundButton buttonView, boolean isChecked) {
         if (mSliceAction == null || mActionView == null) {
             return;
         }
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java b/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java
index 74dd01d..5b41309 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java
@@ -117,6 +117,11 @@
                 mRowStyle = new RowStyle(context, rowStyleRes);
             }
 
+            int defaultRowMinHeight = context.getResources().getDimensionPixelSize(
+                    R.dimen.abc_slice_row_min_height);
+            mRowMinHeight = (int) a.getDimension(
+                    R.styleable.SliceView_rowMinHeight, defaultRowMinHeight);
+
             int defaultRowMaxHeight = context.getResources().getDimensionPixelSize(
                     R.dimen.abc_slice_row_max_height);
             mRowMaxHeight = (int) a.getDimension(
@@ -142,7 +147,6 @@
 
         mRowTextWithRangeHeight = r.getDimensionPixelSize(
                 R.dimen.abc_slice_row_range_multi_text_height);
-        mRowMinHeight = r.getDimensionPixelSize(R.dimen.abc_slice_row_min_height);
         mRowSelectionHeight = r.getDimensionPixelSize(R.dimen.abc_slice_row_selection_height);
         mRowTextWithSelectionHeight = r.getDimensionPixelSize(
                 R.dimen.abc_slice_row_selection_multi_text_height);
@@ -161,6 +165,10 @@
         mListLargeHeight = r.getDimensionPixelSize(R.dimen.abc_slice_large_height);
     }
 
+    public int getRowMinHeight() {
+        return mRowMinHeight;
+    }
+
     public int getRowMaxHeight() {
         return mRowMaxHeight;
     }
diff --git a/slices/view/src/main/java/androidx/slice/widget/TemplateView.java b/slices/view/src/main/java/androidx/slice/widget/TemplateView.java
index a331ec1..02cc488 100644
--- a/slices/view/src/main/java/androidx/slice/widget/TemplateView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/TemplateView.java
@@ -170,6 +170,18 @@
     public void setStyle(SliceStyle style) {
         super.setStyle(style);
         mAdapter.setStyle(style);
+        applyRowStyle();
+    }
+
+    private void applyRowStyle() {
+        if (mSliceStyle == null || mSliceStyle.getRowStyle() == null) {
+            return;
+        }
+
+        final RowStyle rowStyle = mSliceStyle.getRowStyle();
+        if (rowStyle.getDisableRecyclerViewItemAnimator()) {
+            mRecyclerView.setItemAnimator(null);
+        }
     }
 
     @Override
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 0442c73..fdfebd8 100644
--- a/slices/view/src/main/res-public/values/public_attrs.xml
+++ b/slices/view/src/main/res-public/values/public_attrs.xml
@@ -46,6 +46,7 @@
     <public type="attr" name="bottomDividerStartPadding" />
     <public type="attr" name="bottomDividerEndPadding" />
     <public type="attr" name="actionDividerHeight" />
+    <public type="attr" name="rowMinHeight" />
     <public type="attr" name="rowMaxHeight" />
     <public type="attr" name="rowRangeHeight" />
     <public type="attr" name="rowRangeSingleTextHeight" />
@@ -54,4 +55,6 @@
     <public type="attr" name="progressBarStartPadding" />
     <public type="attr" name="progressBarEndPadding" />
     <public type="attr" name="iconSize" />
+    <public type="attr" name="imageSize" />
+    <public type="attr" name="disableRecyclerViewItemAnimator" />
 </resources>
diff --git a/slices/view/src/main/res/values/attrs.xml b/slices/view/src/main/res/values/attrs.xml
index 8c16813..b0e64ce 100644
--- a/slices/view/src/main/res/values/attrs.xml
+++ b/slices/view/src/main/res/values/attrs.xml
@@ -59,6 +59,8 @@
              may set this in your app theme pointing to your custom RowView style.-->
         <attr name="rowStyle" format="reference" />
 
+        <!-- Min height of row view; default size if one line of text -->
+        <attr name="rowMinHeight" format="dimension" />
         <!-- Size of row view with two lines of text -->
         <attr name="rowMaxHeight" format="dimension" />
         <!-- Size of range area in a row to fit a slider or progress bar -->
@@ -117,5 +119,10 @@
 
         <!-- Size of icon. -->
         <attr name="iconSize" format="dimension" />
+        <!-- Size of small images in a slice. -->
+        <attr name="imageSize" format="dimension" />
+        <!-- Control whether RecyclerView item animator is disable or not, true for disable
+        otherwise enable. -->
+        <attr name="disableRecyclerViewItemAnimator" format="boolean" />
     </declare-styleable>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/startup/startup-runtime/build.gradle b/startup/startup-runtime/build.gradle
index aeb135f..ef99fb7 100644
--- a/startup/startup-runtime/build.gradle
+++ b/startup/startup-runtime/build.gradle
@@ -28,6 +28,9 @@
 }
 
 android {
+    buildTypes.all {
+        consumerProguardFiles 'proguard-rules.pro'
+    }
     compileOptions {
         sourceCompatibility = JavaVersion.VERSION_1_7
         targetCompatibility = JavaVersion.VERSION_1_7
diff --git a/startup/startup-runtime/proguard-rules.pro b/startup/startup-runtime/proguard-rules.pro
index f55c09a..b1048d8 100644
--- a/startup/startup-runtime/proguard-rules.pro
+++ b/startup/startup-runtime/proguard-rules.pro
@@ -2,7 +2,7 @@
 # This is because they are discovered and instantiated during application initialization.
 -keep class * extends androidx.startup.Initializer {
     # Keep the public no-argument constructor while allowing other methods to be optimized.
-    public <init>();
+    <init>();
 }
 
 -assumenosideeffects class androidx.startup.StartupLogger
diff --git a/textclassifier/textclassifier/api/1.0.0-alpha03.txt b/textclassifier/textclassifier/api/1.0.0-alpha03.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/1.0.0-alpha03.txt
+++ b/textclassifier/textclassifier/api/1.0.0-alpha03.txt
@@ -271,7 +271,7 @@
   }
 
   public final class TextLinksParams {
-    field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+    field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
   }
 
   public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/api_lint.ignore b/textclassifier/textclassifier/api/api_lint.ignore
index b4fcb1d..aec5e8c 100644
--- a/textclassifier/textclassifier/api/api_lint.ignore
+++ b/textclassifier/textclassifier/api/api_lint.ignore
@@ -47,7 +47,5 @@
     Missing nullability on method `createSpan` return
 MissingNullability: androidx.textclassifier.TextLinks.TextLink#getConfidenceScore(String) parameter #0:
     Missing nullability on parameter `entityType` in method `getConfidenceScore`
-MissingNullability: androidx.textclassifier.TextLinksParams#DEFAULT_PARAMS:
-    Missing nullability on field `DEFAULT_PARAMS` in class `class androidx.textclassifier.TextLinksParams`
 MissingNullability: androidx.textclassifier.TextSelection#getConfidenceScore(String) parameter #0:
     Missing nullability on parameter `entity` in method `getConfidenceScore`
diff --git a/textclassifier/textclassifier/api/current.txt b/textclassifier/textclassifier/api/current.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/current.txt
+++ b/textclassifier/textclassifier/api/current.txt
@@ -271,7 +271,7 @@
   }
 
   public final class TextLinksParams {
-    field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+    field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
   }
 
   public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt b/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt
+++ b/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt
@@ -271,7 +271,7 @@
   }
 
   public final class TextLinksParams {
-    field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+    field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
   }
 
   public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/public_plus_experimental_current.txt b/textclassifier/textclassifier/api/public_plus_experimental_current.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/public_plus_experimental_current.txt
+++ b/textclassifier/textclassifier/api/public_plus_experimental_current.txt
@@ -271,7 +271,7 @@
   }
 
   public final class TextLinksParams {
-    field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+    field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
   }
 
   public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt b/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt
index 3e183d8..2ab5708 100644
--- a/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt
+++ b/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt
@@ -318,7 +318,7 @@
   }
 
   public final class TextLinksParams {
-    field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+    field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
   }
 
   public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/restricted_current.txt b/textclassifier/textclassifier/api/restricted_current.txt
index 3e183d8..2ab5708 100644
--- a/textclassifier/textclassifier/api/restricted_current.txt
+++ b/textclassifier/textclassifier/api/restricted_current.txt
@@ -318,7 +318,7 @@
   }
 
   public final class TextLinksParams {
-    field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+    field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
   }
 
   public static final class TextLinksParams.Builder {
diff --git a/tv-provider/tv-provider/api/api_lint.ignore b/tv-provider/tv-provider/api/api_lint.ignore
index 7c43e2f..783a749 100644
--- a/tv-provider/tv-provider/api/api_lint.ignore
+++ b/tv-provider/tv-provider/api/api_lint.ignore
@@ -305,12 +305,6 @@
     Missing nullability on method `downloadBitmap` return
 MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getAllChannels():
     Missing nullability on method `getAllChannels` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getPreviewChannel(long):
-    Missing nullability on method `getPreviewChannel` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getPreviewProgram(long):
-    Missing nullability on method `getPreviewProgram` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getWatchNextProgram(long):
-    Missing nullability on method `getWatchNextProgram` return
 MissingNullability: androidx.tvprovider.media.tv.PreviewProgram#fromCursor(android.database.Cursor):
     Missing nullability on method `fromCursor` return
 MissingNullability: androidx.tvprovider.media.tv.PreviewProgram#fromCursor(android.database.Cursor) parameter #0:
diff --git a/ui/integration-tests/benchmark/build.gradle b/ui/integration-tests/benchmark/build.gradle
index 407eb1e..40db4f5 100644
--- a/ui/integration-tests/benchmark/build.gradle
+++ b/ui/integration-tests/benchmark/build.gradle
@@ -36,6 +36,7 @@
     implementation project(":compose:compose-runtime")
     implementation project(":ui:integration-tests")
     implementation project(":ui:ui-test")
+    implementation project(":ui:ui-layout")
     implementation(KOTLIN_STDLIB)
     implementation(KOTLIN_REFLECT)
     implementation(ANDROIDX_TEST_RULES)
diff --git a/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml b/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml
index a7345d6..1983f55 100644
--- a/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml
+++ b/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,7 +23,11 @@
       ~ requestLegacyExternalStorage to enable legacy JSON reporting when targeting Q
       -->
     <application
-        android:requestLegacyExternalStorage="true"
-        android:debuggable="false"
-        tools:replace="android:debuggable" />
+            android:requestLegacyExternalStorage="true"
+            android:debuggable="false"
+            tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
+    </application>
 </manifest>
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
new file mode 100644
index 0000000..e3efcc0
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
@@ -0,0 +1,145 @@
+/*
+ * 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.benchmark.test
+
+import android.view.ViewGroup
+import androidx.activity.ComponentActivity
+import androidx.benchmark.junit4.BenchmarkRule
+import androidx.benchmark.junit4.measureRepeated
+import androidx.test.filters.LargeTest
+import androidx.ui.core.AndroidOwner
+import androidx.ui.core.LayoutNode
+import androidx.ui.core.Modifier
+import androidx.ui.core.drawBehind
+import androidx.ui.core.drawLayer
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.core.keyinput.keyInputFilter
+import androidx.ui.core.layoutId
+import androidx.ui.core.onPositioned
+import androidx.ui.core.semantics.semantics
+import androidx.ui.core.setContent
+import androidx.ui.core.zIndex
+import androidx.ui.foundation.Box
+import androidx.ui.layout.padding
+import androidx.ui.test.DisableTransitions
+import androidx.ui.unit.dp
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.model.Statement
+
+/**
+ * Benchmark that sets the [LayoutNode.modifier].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class LayoutNodeModifierBenchmark(
+    private val numberOfModifiers: Int
+) {
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "modifiers={0}")
+        fun initParameters(): Array<Any> = arrayOf(1, 5, 10)
+    }
+
+    @get:Rule
+    val rule = SimpleAndroidBenchmarkRule()
+
+    var modifiers = emptyList<Modifier>()
+    var combinedModifier: Modifier = Modifier
+    lateinit var layoutNode: LayoutNode
+
+    @Before
+    fun setup() {
+        modifiers = listOf(
+            Modifier.padding(10.dp),
+            Modifier.drawBehind { },
+            Modifier.drawLayer(),
+            Modifier.keyInputFilter { _ -> true },
+            Modifier.semantics(),
+            Modifier.pressIndicatorGestureFilter(),
+            Modifier.layoutId("Hello"),
+            Modifier.padding(10.dp),
+            Modifier.onPositioned { _ -> },
+            Modifier.zIndex(1f)
+        ).subList(0, numberOfModifiers)
+
+        combinedModifier = modifiers.fold<Modifier, Modifier>(Modifier) { acc, modifier ->
+            acc + modifier
+        }
+
+        rule.activityTestRule.runOnUiThread {
+            rule.activityTestRule.activity.setContent { Box() }
+        }
+        rule.activityTestRule.runOnUiThread {
+            val composeView = rule.findAndroidOwner()
+            val root = composeView.root
+            val selection = root.children[0]
+            check(selection.children.size == 1) { "Expecting only a Box" }
+            layoutNode = selection.children[0]
+            check(layoutNode.children.isEmpty()) { "Box should be empty" }
+        }
+    }
+
+    @Test
+    fun setAndClearModifiers() {
+        rule.activityTestRule.runOnUiThread {
+            rule.benchmarkRule.measureRepeated {
+                layoutNode.modifier = combinedModifier
+                layoutNode.modifier = Modifier
+            }
+        }
+    }
+
+    @Test
+    fun smallModifierChange() {
+        rule.activityTestRule.runOnUiThread {
+            val altModifier = Modifier.padding(10.dp) + combinedModifier
+            layoutNode.modifier = altModifier
+
+            rule.benchmarkRule.measureRepeated {
+                layoutNode.modifier = combinedModifier
+                layoutNode.modifier = altModifier
+            }
+        }
+    }
+
+    class SimpleAndroidBenchmarkRule() : TestRule {
+        @Suppress("DEPRECATION")
+        val activityTestRule =
+            androidx.test.rule.ActivityTestRule<ComponentActivity>(ComponentActivity::class.java)
+
+        val benchmarkRule = BenchmarkRule()
+
+        private val disableTransitionsRule = DisableTransitions()
+
+        override fun apply(base: Statement, description: Description?): Statement {
+            val statement = benchmarkRule.apply(
+                activityTestRule.apply(base, description), description!!)
+            return disableTransitionsRule.apply(statement, description)
+        }
+
+        fun findAndroidOwner(): AndroidOwner {
+            return activityTestRule.activity.findViewById<ViewGroup>(android.R.id.content)
+                .getChildAt(0) as AndroidOwner
+        }
+    }
+}
diff --git a/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt b/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt
index e7e80c0..7bc3203 100644
--- a/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt
+++ b/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt
@@ -21,7 +21,9 @@
 import androidx.compose.setValue
 import androidx.ui.animation.Crossfade
 import androidx.ui.core.Alignment
+import androidx.ui.core.LayoutDirection
 import androidx.ui.core.Modifier
+import androidx.ui.core.WithConstraints
 import androidx.ui.core.testTag
 import androidx.ui.demos.common.ActivityDemo
 import androidx.ui.demos.common.ComposableDemo
@@ -44,6 +46,7 @@
 import androidx.ui.material.TopAppBar
 import androidx.ui.material.icons.Icons
 import androidx.ui.material.icons.filled.ArrowBack
+import androidx.ui.material.icons.filled.ArrowForward
 import androidx.ui.material.icons.filled.Search
 import androidx.ui.material.icons.filled.Settings
 import androidx.ui.savedinstancestate.savedInstanceState
@@ -61,11 +64,7 @@
     onNavigateUp: () -> Unit,
     launchSettings: () -> Unit
 ) {
-    val navigationIcon = (@Composable {
-        IconButton(onClick = onNavigateUp) {
-            Icon(Icons.Filled.ArrowBack)
-        }
-    }).takeIf { canNavigateUp }
+    val navigationIcon = (@Composable { AppBarIcons.Back(onNavigateUp) }).takeIf { canNavigateUp }
 
     var filterText by savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
 
@@ -173,6 +172,19 @@
 
 private object AppBarIcons {
     @Composable
+    fun Back(onClick: () -> Unit) {
+        WithConstraints {
+            val icon = when (layoutDirection) {
+                LayoutDirection.Ltr -> Icons.Filled.ArrowBack
+                LayoutDirection.Rtl -> Icons.Filled.ArrowForward
+            }
+            IconButton(onClick = onClick) {
+                Icon(icon)
+            }
+        }
+    }
+
+    @Composable
     fun Filter(onClick: () -> Unit) {
         IconButton(modifier = Modifier.testTag(Tags.FilterButton), onClick = onClick) {
             Icon(Icons.Filled.Search)
diff --git a/ui/settings.gradle b/ui/settings.gradle
index 936c7f3..a62c916 100644
--- a/ui/settings.gradle
+++ b/ui/settings.gradle
@@ -43,6 +43,7 @@
 includeProject(":compose:compose-compiler", "../compose/compose-compiler")
 includeProject(":compose:compose-compiler-hosted", "../compose/compose-compiler-hosted")
 includeProject(":compose:compose-compiler-hosted:integration-tests", "../compose/compose-compiler-hosted/integration-tests")
+includeProject(":compose:compose-dispatch", "../compose/compose-dispatch")
 includeProject(":compose:compose-runtime", "../compose/compose-runtime")
 includeProject(":compose:compose-runtime-benchmark", "../compose/compose-runtime/compose-runtime-benchmark")
 includeProject(":compose:compose-runtime:samples", "../compose/compose-runtime/samples")
@@ -62,6 +63,7 @@
 includeProject(":ui:ui-animation-core:samples", "ui-animation-core/samples")
 includeProject(":ui:ui-animation:integration-tests:ui-animation-demos", "ui-animation/integration-tests/animation-demos")
 includeProject(":ui:ui-animation:samples", "ui-animation/samples")
+includeProject(":ui:ui-animation-tooling", "ui-animation-tooling")
 includeProject(":ui:ui-core", "ui-core")
 includeProject(":ui:ui-core:integration-tests:ui-core-demos", "ui-core/integration-tests/ui-core-demos")
 includeProject(":ui:ui-core:samples", "ui-core/samples")
diff --git a/ui/ui-android-view/build.gradle b/ui/ui-android-view/build.gradle
index efb20b7..7d716ba 100644
--- a/ui/ui-android-view/build.gradle
+++ b/ui/ui-android-view/build.gradle
@@ -62,7 +62,7 @@
 
 androidx {
     name = "AndroidX UI View components"
-    publish = Publish.SNAPSHOT_AND_RELEASE
+    publish = Publish.NONE
     mavenVersion = LibraryVersions.UI
     mavenGroup = LibraryGroups.UI
     inceptionYear = "2019"
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt
index b4b39a0..b416598 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt
+++ b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt
@@ -20,7 +20,6 @@
 import android.widget.FrameLayout
 import androidx.compose.Composable
 import androidx.compose.Recomposer
-import androidx.compose.escapeCompose
 import androidx.ui.core.ContextAmbient
 import androidx.ui.core.setContent
 import androidx.ui.demos.common.ComposableDemo
@@ -57,12 +56,11 @@
 
 @Composable
 fun AndroidWithCompose(context: Context, children: @Composable () -> Unit) {
-    val anotherLayout =
-        escapeCompose { FrameLayout(context) }.also { view ->
-            view.setContent(Recomposer.current()) {
-                children()
-            }
-            view.setPadding(50, 50, 50, 50)
+    val anotherLayout = FrameLayout(context).also { view ->
+        view.setContent(Recomposer.current()) {
+            children()
         }
+        view.setPadding(50, 50, 50, 50)
+    }
     AndroidView(anotherLayout)
 }
\ No newline at end of file
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt
index 0bededb..400a60b 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt
+++ b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt
@@ -47,6 +47,7 @@
 import androidx.ui.androidview.WebComponent
 import androidx.ui.androidview.WebContext
 import androidx.ui.core.setViewContent
+import androidx.ui.viewinterop.emitView
 
 @Stable
 class WebParams {
@@ -65,7 +66,7 @@
                 Log.e("WebCompAct", "setContent")
             }
 
-            FrameLayout {
+            emitView(::FrameLayout, {}) {
                 renderViews(webContext = webContext)
             }
         }
@@ -94,52 +95,56 @@
         }
     }
 
-    LinearLayout(
-        orientation = LinearLayout.VERTICAL,
-        layoutWidth = MATCH_PARENT,
-        layoutHeight = MATCH_PARENT
-    ) {
-        LinearLayout(
-            orientation = LinearLayout.HORIZONTAL,
-            layoutWidth = MATCH_PARENT,
-            layoutHeight = WRAP_CONTENT,
-            weightSum = 1f
-        ) {
-            Button(
-                layoutWidth = 40.dp,
-                layoutHeight = WRAP_CONTENT,
-                text = "",
-                onClick = {
+    emitView(::LinearLayout, {
+        it.orientation = LinearLayout.VERTICAL
+        it.setLayoutWidth(MATCH_PARENT)
+        it.setLayoutHeight(MATCH_PARENT)
+    }) {
+        emitView(::LinearLayout, {
+            it.orientation = LinearLayout.HORIZONTAL
+            it.setLayoutWidth(MATCH_PARENT)
+            it.setLayoutHeight(WRAP_CONTENT)
+            it.weightSum = 1f
+        }) {
+            emitView(::Button) {
+                it.setLayoutWidth(40.dp)
+                it.setLayoutHeight(WRAP_CONTENT)
+                it.text = ""
+                it.setOnClickListener {
                     webContext.goBack()
-                })
-            Button(
-                layoutWidth = 40.dp,
-                layoutHeight = WRAP_CONTENT,
-                text = ") {",
-                onClick = {
+                }
+            }
+            emitView(::Button) {
+                it.setLayoutWidth(40.dp)
+                it.setLayoutHeight(WRAP_CONTENT)
+                it.text = ""
+                it.setOnClickListener {
                     webContext.goForward()
-                })
-            EditText(
-                layoutWidth = 0.dp,
-                layoutHeight = WRAP_CONTENT,
-                layoutWeight = 1f,
-                singleLine = true,
-                controlledText = displayedUrl.value,
-                onTextChanged = { s: CharSequence?, _, _, _ ->
+                }
+            }
+            emitView(::EditText) {
+                it.setLayoutWidth(0.dp)
+                it.setLayoutHeight(WRAP_CONTENT)
+                it.setLayoutWeight(1f)
+                it.isSingleLine = true
+                it.setControlledText(displayedUrl.value)
+                it.setOnTextChanged { s: CharSequence?, _, _, _ ->
                     displayedUrl.value = s.toString()
-                })
-            Button(
-                layoutWidth = WRAP_CONTENT,
-                layoutHeight = WRAP_CONTENT,
-                text = "Go",
-                onClick = {
+                }
+            }
+            emitView(::Button) {
+                it.setLayoutWidth(WRAP_CONTENT)
+                it.setLayoutHeight(WRAP_CONTENT)
+                it.text = "Go"
+                it.setOnClickListener {
                     if (displayedUrl.value.isNotBlank()) {
                         if (WebContext.debug) {
                             Log.d("WebCompAct", "setting url to " + displayedUrl.value)
                         }
                         webParams.url = displayedUrl.value
                     }
-                })
+                }
+            }
         }
 
         if (WebContext.debug) {
diff --git a/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt b/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt
index 5b89d14..1203662 100644
--- a/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt
+++ b/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt
@@ -21,6 +21,7 @@
 import android.webkit.WebView
 import android.webkit.WebViewClient
 import androidx.compose.Composable
+import androidx.ui.viewinterop.emitView
 
 class WebContext {
 
@@ -80,8 +81,9 @@
         Log.d("WebComponent", "WebComponent compose " + url)
     }
 
-    WebView(
-        ref = { webContext.webView = it },
-        url = url,
-        webViewClient = webViewClient)
+    emitView(::WebView) {
+        it.setRef { view -> webContext.webView = view }
+        it.setUrl(url)
+        it.webViewClient = webViewClient
+    }
 }
diff --git a/ui/ui-animation-core/api/0.1.0-dev15.txt b/ui/ui-animation-core/api/0.1.0-dev15.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/0.1.0-dev15.txt
+++ b/ui/ui-animation-core/api/0.1.0-dev15.txt
@@ -60,6 +60,8 @@
   }
 
   public enum AnimationEndReason {
+    method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.AnimationEndReason[] values();
     enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
     enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
     enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
     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;
+    field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
   }
 
   public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
   }
 
   public enum InterruptionHandling {
+    method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.InterruptionHandling[] values();
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
     enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
     field public static final float DampingRatioMediumBouncy = 0.5f;
     field public static final float DampingRatioNoBouncy = 1.0f;
     field public static final float DefaultDisplacementThreshold = 0.01f;
-    field public static final androidx.animation.Spring! INSTANCE;
+    field public static final androidx.animation.Spring INSTANCE;
     field public static final float StiffnessHigh = 10000.0f;
     field public static final float StiffnessLow = 200.0f;
     field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/api_lint.ignore b/ui/ui-animation-core/api/api_lint.ignore
index 35e0da1..a5bb439 100644
--- a/ui/ui-animation-core/api/api_lint.ignore
+++ b/ui/ui-animation-core/api/api_lint.ignore
@@ -17,8 +17,6 @@
 
 CallbackName: androidx.animation.AnimationClockObserver:
     Class should be named AnimationClockCallback
-CallbackName: androidx.animation.TransitionAnimation.TransitionAnimationClockObserver:
-    Class should be named TransitionAnimationClockCallback
 
 
 DocumentExceptions: androidx.animation.DurationBasedAnimationBuilder#setDelay(int):
diff --git a/ui/ui-animation-core/api/current.txt b/ui/ui-animation-core/api/current.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/current.txt
+++ b/ui/ui-animation-core/api/current.txt
@@ -60,6 +60,8 @@
   }
 
   public enum AnimationEndReason {
+    method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.AnimationEndReason[] values();
     enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
     enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
     enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
     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;
+    field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
   }
 
   public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
   }
 
   public enum InterruptionHandling {
+    method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.InterruptionHandling[] values();
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
     enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
     field public static final float DampingRatioMediumBouncy = 0.5f;
     field public static final float DampingRatioNoBouncy = 1.0f;
     field public static final float DefaultDisplacementThreshold = 0.01f;
-    field public static final androidx.animation.Spring! INSTANCE;
+    field public static final androidx.animation.Spring INSTANCE;
     field public static final float StiffnessHigh = 10000.0f;
     field public static final float StiffnessLow = 200.0f;
     field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -60,6 +60,8 @@
   }
 
   public enum AnimationEndReason {
+    method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.AnimationEndReason[] values();
     enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
     enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
     enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
     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;
+    field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
   }
 
   public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
   }
 
   public enum InterruptionHandling {
+    method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.InterruptionHandling[] values();
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
     enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
     field public static final float DampingRatioMediumBouncy = 0.5f;
     field public static final float DampingRatioNoBouncy = 1.0f;
     field public static final float DefaultDisplacementThreshold = 0.01f;
-    field public static final androidx.animation.Spring! INSTANCE;
+    field public static final androidx.animation.Spring INSTANCE;
     field public static final float StiffnessHigh = 10000.0f;
     field public static final float StiffnessLow = 200.0f;
     field public static final float StiffnessMedium = 1500.0f;
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 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_current.txt
@@ -60,6 +60,8 @@
   }
 
   public enum AnimationEndReason {
+    method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.AnimationEndReason[] values();
     enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
     enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
     enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
     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;
+    field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
   }
 
   public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
   }
 
   public enum InterruptionHandling {
+    method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.InterruptionHandling[] values();
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
     enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
     field public static final float DampingRatioMediumBouncy = 0.5f;
     field public static final float DampingRatioNoBouncy = 1.0f;
     field public static final float DefaultDisplacementThreshold = 0.01f;
-    field public static final androidx.animation.Spring! INSTANCE;
+    field public static final androidx.animation.Spring INSTANCE;
     field public static final float StiffnessHigh = 10000.0f;
     field public static final float StiffnessLow = 200.0f;
     field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt b/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt
@@ -60,6 +60,8 @@
   }
 
   public enum AnimationEndReason {
+    method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.AnimationEndReason[] values();
     enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
     enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
     enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
     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;
+    field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
   }
 
   public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
   }
 
   public enum InterruptionHandling {
+    method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.InterruptionHandling[] values();
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
     enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
     field public static final float DampingRatioMediumBouncy = 0.5f;
     field public static final float DampingRatioNoBouncy = 1.0f;
     field public static final float DefaultDisplacementThreshold = 0.01f;
-    field public static final androidx.animation.Spring! INSTANCE;
+    field public static final androidx.animation.Spring INSTANCE;
     field public static final float StiffnessHigh = 10000.0f;
     field public static final float StiffnessLow = 200.0f;
     field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/restricted_current.txt b/ui/ui-animation-core/api/restricted_current.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/restricted_current.txt
+++ b/ui/ui-animation-core/api/restricted_current.txt
@@ -60,6 +60,8 @@
   }
 
   public enum AnimationEndReason {
+    method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.AnimationEndReason[] values();
     enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
     enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
     enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
     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;
+    field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
   }
 
   public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
   }
 
   public enum InterruptionHandling {
+    method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.animation.InterruptionHandling[] values();
     enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
     enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
     enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
     field public static final float DampingRatioMediumBouncy = 0.5f;
     field public static final float DampingRatioNoBouncy = 1.0f;
     field public static final float DefaultDisplacementThreshold = 0.01f;
-    field public static final androidx.animation.Spring! INSTANCE;
+    field public static final androidx.animation.Spring INSTANCE;
     field public static final float StiffnessHigh = 10000.0f;
     field public static final float StiffnessLow = 200.0f;
     field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-tooling/OWNERS b/ui/ui-animation-tooling/OWNERS
new file mode 100644
index 0000000..13f1a9c
--- /dev/null
+++ b/ui/ui-animation-tooling/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
\ No newline at end of file
diff --git a/ui/ui-animation-tooling/api/0.1.0-dev15.txt b/ui/ui-animation-tooling/api/0.1.0-dev15.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/0.1.0-dev15.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+  public interface ComposeAnimation {
+    method public Object getAnimation();
+    method public default java.util.Set<java.lang.Object> getStates();
+    method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+  }
+
+  public enum ComposeAnimationType {
+    method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+  }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/current.txt b/ui/ui-animation-tooling/api/current.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+  public interface ComposeAnimation {
+    method public Object getAnimation();
+    method public default java.util.Set<java.lang.Object> getStates();
+    method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+  }
+
+  public enum ComposeAnimationType {
+    method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+  }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-animation-tooling/api/public_plus_experimental_0.1.0-dev15.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/public_plus_experimental_0.1.0-dev15.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+  public interface ComposeAnimation {
+    method public Object getAnimation();
+    method public default java.util.Set<java.lang.Object> getStates();
+    method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+  }
+
+  public enum ComposeAnimationType {
+    method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+  }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/public_plus_experimental_current.txt b/ui/ui-animation-tooling/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/public_plus_experimental_current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+  public interface ComposeAnimation {
+    method public Object getAnimation();
+    method public default java.util.Set<java.lang.Object> getStates();
+    method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+  }
+
+  public enum ComposeAnimationType {
+    method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+  }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/restricted_0.1.0-dev15.txt b/ui/ui-animation-tooling/api/restricted_0.1.0-dev15.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/restricted_0.1.0-dev15.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+  public interface ComposeAnimation {
+    method public Object getAnimation();
+    method public default java.util.Set<java.lang.Object> getStates();
+    method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+  }
+
+  public enum ComposeAnimationType {
+    method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+  }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/restricted_current.txt b/ui/ui-animation-tooling/api/restricted_current.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/restricted_current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+  public interface ComposeAnimation {
+    method public Object getAnimation();
+    method public default java.util.Set<java.lang.Object> getStates();
+    method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+  }
+
+  public enum ComposeAnimationType {
+    method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+    enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+  }
+
+}
+
diff --git a/ui/ui-animation-tooling/build.gradle b/ui/ui-animation-tooling/build.gradle
new file mode 100644
index 0000000..9dea25f
--- /dev/null
+++ b/ui/ui-animation-tooling/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+
+import static androidx.build.dependencies.DependenciesKt.getKOTLIN_STDLIB
+
+plugins {
+    id("AndroidXPlugin")
+    id("kotlin")
+}
+
+dependencies {
+    implementation(KOTLIN_STDLIB)
+}
+
+androidx {
+    name = "Compose Animation Tooling"
+    publish = Publish.SNAPSHOT_AND_RELEASE
+    mavenVersion = LibraryVersions.UI
+    mavenGroup = LibraryGroups.UI
+    generateDocs = false
+}
diff --git a/ui/ui-animation-tooling/src/main/java/androidx/ui/animation/tooling/ComposeAnimation.kt b/ui/ui-animation-tooling/src/main/java/androidx/ui/animation/tooling/ComposeAnimation.kt
new file mode 100644
index 0000000..bffdb24
--- /dev/null
+++ b/ui/ui-animation-tooling/src/main/java/androidx/ui/animation/tooling/ComposeAnimation.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.animation.tooling
+
+/**
+ * Type of the animation. Different types might have different properties, for example a
+ * `TransitionAnimation` (represented by [TRANSITION_ANIMATION]) has a set of states associated
+ * with it.
+ */
+enum class ComposeAnimationType {
+    TRANSITION_ANIMATION, ANIMATED_VALUE
+}
+
+/**
+ * Simple interface to make it easier to share Compose animation objects between `ui-tooling` and
+ * Android Studio. Since both ends communicate mostly using bytecode manipulation and reflection,
+ * being able to parse these objects into a common type makes
+ */
+interface ComposeAnimation {
+
+    /**
+     * Returns the animation type. Ideally, the type should be checked before calling methods
+     * specific to a certain type, e.g. [getStates].
+     */
+    fun getType(): ComposeAnimationType
+
+    /**
+     * Returns the actual animation object.
+     */
+    fun getAnimation(): Any
+
+    /**
+     * Returns all the available states of a `TransitionAnimation`.
+     *
+     * @throws UnsupportedOperationException if [getType] does not return `TRANSITION_ANIMATION`.
+     */
+    fun getStates(): Set<Any> {
+        throw UnsupportedOperationException("Only available when getType() is TRANSITION_ANIMATION")
+    }
+}
diff --git a/ui/ui-core/api/0.1.0-dev15.txt b/ui/ui-core/api/0.1.0-dev15.txt
index 0b0b3f7..634d280 100644
--- a/ui/ui-core/api/0.1.0-dev15.txt
+++ b/ui/ui-core/api/0.1.0-dev15.txt
@@ -1,12 +1,4 @@
 // Signature format: 3.0
-package androidx.compose {
-
-  public final class ComposerCompatKt {
-    method @Deprecated public static androidx.ui.node.UiComposer getComposer();
-  }
-
-}
-
 package androidx.ui.autofill {
 
   public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
   }
 
   public enum AutofillType {
+    method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.autofill.AutofillType[] values();
     enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
   @androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
     method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
-    field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+    field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
   }
 
   public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
 
   @androidx.compose.Immutable public interface Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
-    field public static final androidx.ui.core.Alignment.Companion! Companion;
+    field public static final androidx.ui.core.Alignment.Companion Companion;
   }
 
   public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class AlignmentLine {
-    field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+    field public static final androidx.ui.core.AlignmentLine.Companion Companion;
     field public static final int Unspecified = -2147483648; // 0x80000000
   }
 
@@ -256,7 +250,7 @@
 
   @androidx.compose.Stable public interface ContentScale {
     method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
-    field public static final androidx.ui.core.ContentScale.Companion! Companion;
+    field public static final androidx.ui.core.ContentScale.Companion Companion;
   }
 
   public static final class ContentScale.Companion {
@@ -290,6 +284,8 @@
   }
 
   public enum Direction {
+    method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.Direction[] values();
     enum_constant public static final androidx.ui.core.Direction DOWN;
     enum_constant public static final androidx.ui.core.Direction LEFT;
     enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -342,6 +338,8 @@
   }
 
   public enum DropDownAlignment {
+    method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.DropDownAlignment[] values();
     enum_constant public static final androidx.ui.core.DropDownAlignment End;
     enum_constant public static final androidx.ui.core.DropDownAlignment Start;
   }
@@ -423,7 +421,6 @@
     method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
-    method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
   }
 
@@ -445,7 +442,6 @@
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
     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.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -476,7 +472,6 @@
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
     method public void setDepth(int p);
-    method @Deprecated public void setHandlesParentData(boolean 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);
@@ -486,7 +481,6 @@
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
     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 isPlaced;
     property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -503,6 +497,8 @@
   }
 
   public enum LayoutNode.LayoutState {
+    method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutNode.LayoutState[] values();
     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;
@@ -584,7 +580,7 @@
     method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
     method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
     method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
-    field public static final androidx.ui.core.Modifier.Companion! Companion;
+    field public static final androidx.ui.core.Modifier.Companion Companion;
   }
 
   public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -634,12 +630,15 @@
     method public void drawLayer(androidx.ui.graphics.Canvas canvas);
     method public long getLayerId();
     method public android.graphics.Matrix getMatrix();
+    method public androidx.ui.core.DrawLayerModifier getModifier();
     method public void invalidate();
     method public void move(androidx.ui.unit.IntOffset position);
     method public void resize(androidx.ui.unit.IntSize size);
+    method public void setModifier(androidx.ui.core.DrawLayerModifier p);
     method public void updateDisplayList();
     method public void updateLayerProperties();
     property public abstract long layerId;
+    property public abstract androidx.ui.core.DrawLayerModifier modifier;
   }
 
   public interface Owner {
@@ -684,7 +683,7 @@
     property public abstract boolean showLayoutBounds;
     property public abstract androidx.ui.input.TextInputService textInputService;
     property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
-    field public static final androidx.ui.core.Owner.Companion! Companion;
+    field public static final androidx.ui.core.Owner.Companion Companion;
   }
 
   public static final class Owner.Companion {
@@ -734,6 +733,8 @@
   }
 
   public enum PointerEventPass {
+    method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.PointerEventPass[] values();
     enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -813,7 +814,6 @@
   }
 
   public final class TestTagKt {
-    method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
   }
 
@@ -826,7 +826,7 @@
     method public static float getPivotFractionY-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Immutable public static inline String! toString-impl(long p);
-    field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+    field public static final androidx.ui.core.TransformOrigin.Companion Companion;
   }
 
   public static final class TransformOrigin.Companion {
@@ -859,8 +859,8 @@
     method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
   }
 
   public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -889,6 +889,8 @@
 package androidx.ui.core.focus {
 
   public enum FocusDetailedState {
+    method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusDetailedState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -913,6 +915,8 @@
   }
 
   public enum FocusState {
+    method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusState Focused;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -962,7 +966,10 @@
   }
 
   public final class DragSlopExceededGestureFilterKt {
-    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+  }
+
+  @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
   }
 
   public final class GestureUtilsKt {
@@ -990,7 +997,7 @@
   }
 
   public final class RawDragGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
   }
 
   public final class RawPressStartGestureFilterKt {
@@ -1026,6 +1033,17 @@
   public final class ScaleUtilKt {
   }
 
+  public interface ScrollCallback {
+    method public default void onCancel();
+    method public default float onScroll(float scrollDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(float velocity);
+  }
+
+  public final class ScrollGestureFilterKt {
+    method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+  }
+
   public final class TapGestureFilterKt {
     method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
@@ -1045,13 +1063,36 @@
   }
 
   public enum DelayUpMessage {
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
   }
 
   public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
-    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+  }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+  public enum Orientation {
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+  }
+
+  @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+    ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+    method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public void onCancel();
+    method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
   }
 
 }
@@ -1080,6 +1121,8 @@
   }
 
   public enum HapticFeedbackType {
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
   }
@@ -1113,7 +1156,7 @@
     method public int getKeyCode();
     method public static inline int hashCode-impl(int p);
     method public static String toString-impl(int $this);
-    field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+    field public static final androidx.ui.core.keyinput.Key.Companion Companion;
   }
 
   public static final class Key.Companion {
@@ -1706,6 +1749,8 @@
   }
 
   public enum KeyEventType {
+    method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.keyinput.KeyEventType[] values();
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
   }
@@ -1789,6 +1834,9 @@
   public final class SelectionHandlesKt {
   }
 
+  public final class SelectionLayoutKt {
+  }
+
   public final class SelectionManagerKt {
   }
 
@@ -1838,19 +1886,18 @@
   }
 
   public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
-    method public boolean getApplyToChildLayoutNode();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
-    property public abstract boolean applyToChildLayoutNode;
     property public abstract int id;
     property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
   }
 
   public final class SemanticsModifierKt {
-    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
   }
 
   public final class SemanticsNode {
+    method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.unit.PxBounds getBoundsInRoot();
     method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
     method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1873,7 +1920,7 @@
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
     property public final androidx.ui.unit.IntSize size;
-    field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+    field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
   }
 
   public static final class SemanticsNode.Companion {
@@ -1907,6 +1954,8 @@
   }
 
   public enum TextToolbarStatus {
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
   }
@@ -1927,6 +1976,13 @@
     method public final void invalidate();
   }
 
+  public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+    ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+    method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+  }
+
   public final class VectorAsset {
     method public String component1();
     method public float component2();
@@ -1961,8 +2017,8 @@
   }
 
   public final class VectorComposeKt {
-    method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
-    method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+    method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
   }
 
   public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2015,7 +2071,7 @@
 
   public final class VectorPainterKt {
     method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
-    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
     field public static final String RootGroupName = "VectorRootGroup";
   }
 
@@ -2044,9 +2100,6 @@
     method public float getStrokeLineWidth();
   }
 
-  public final class VectorScope {
-  }
-
 }
 
 package androidx.ui.graphics.vector.compat {
@@ -2074,17 +2127,16 @@
   public final class PointerInteropUtilsKt {
   }
 
-  public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
-    ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
-    method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public android.content.Context getContext();
-    method public Object getRoot();
-  }
-
-  public final class UiComposerKt {
+  public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+    ctor public UiApplier(Object root);
+    method public void down(Object node);
+    method public Object getCurrent();
+    method public void insert(int index, Object instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+    method public void reset();
+    method public void up();
+    property public Object current;
   }
 
   public final class ViewInteropKt {
@@ -2209,11 +2261,7 @@
     property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
-    field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
-  }
-
-  public final class SemanticsKt {
-    method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
   }
 
   public final class SemanticsProperties {
@@ -2233,7 +2281,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
-    field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+    field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
   }
 
   public final class SemanticsPropertiesKt {
@@ -2329,6 +2377,11 @@
     method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
   }
 
+  public final class EmitViewKt {
+    method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+    method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+  }
+
 }
 
 package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/api_lint.ignore b/ui/ui-core/api/api_lint.ignore
index 158eb11..4151ff7 100644
--- a/ui/ui-core/api/api_lint.ignore
+++ b/ui/ui-core/api/api_lint.ignore
@@ -29,8 +29,12 @@
     Class should be named ScaleCallback
 
 
-ContextFirst: androidx.ui.core.WrapperKt#subcomposeInto(androidx.ui.core.LayoutNode, android.content.Context, androidx.compose.CompositionReference, kotlin.jvm.functions.Function0<kotlin.Unit>) parameter #1:
-    Context is distinct, so it must be the first argument (method `subcomposeInto`)
+ListenerLast: androidx.ui.core.gesture.ScrollGestureFilterKt#scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>, boolean) parameter #2:
+    Listeners should always be at end of argument list (method `scrollGestureFilter`)
+ListenerLast: androidx.ui.core.gesture.ScrollGestureFilterKt#scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>, boolean) parameter #3:
+    Listeners should always be at end of argument list (method `scrollGestureFilter`)
+ListenerLast: androidx.ui.core.gesture.ScrollGestureFilterKt#scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>, boolean) parameter #4:
+    Listeners should always be at end of argument list (method `scrollGestureFilter`)
 
 
 MissingNullability: androidx.ui.core.Measured#constructor-impl(androidx.ui.core.Placeable):
diff --git a/ui/ui-core/api/current.txt b/ui/ui-core/api/current.txt
index 0b0b3f7..634d280 100644
--- a/ui/ui-core/api/current.txt
+++ b/ui/ui-core/api/current.txt
@@ -1,12 +1,4 @@
 // Signature format: 3.0
-package androidx.compose {
-
-  public final class ComposerCompatKt {
-    method @Deprecated public static androidx.ui.node.UiComposer getComposer();
-  }
-
-}
-
 package androidx.ui.autofill {
 
   public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
   }
 
   public enum AutofillType {
+    method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.autofill.AutofillType[] values();
     enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
   @androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
     method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
-    field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+    field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
   }
 
   public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
 
   @androidx.compose.Immutable public interface Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
-    field public static final androidx.ui.core.Alignment.Companion! Companion;
+    field public static final androidx.ui.core.Alignment.Companion Companion;
   }
 
   public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class AlignmentLine {
-    field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+    field public static final androidx.ui.core.AlignmentLine.Companion Companion;
     field public static final int Unspecified = -2147483648; // 0x80000000
   }
 
@@ -256,7 +250,7 @@
 
   @androidx.compose.Stable public interface ContentScale {
     method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
-    field public static final androidx.ui.core.ContentScale.Companion! Companion;
+    field public static final androidx.ui.core.ContentScale.Companion Companion;
   }
 
   public static final class ContentScale.Companion {
@@ -290,6 +284,8 @@
   }
 
   public enum Direction {
+    method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.Direction[] values();
     enum_constant public static final androidx.ui.core.Direction DOWN;
     enum_constant public static final androidx.ui.core.Direction LEFT;
     enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -342,6 +338,8 @@
   }
 
   public enum DropDownAlignment {
+    method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.DropDownAlignment[] values();
     enum_constant public static final androidx.ui.core.DropDownAlignment End;
     enum_constant public static final androidx.ui.core.DropDownAlignment Start;
   }
@@ -423,7 +421,6 @@
     method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
-    method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
   }
 
@@ -445,7 +442,6 @@
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
     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.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -476,7 +472,6 @@
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
     method public void setDepth(int p);
-    method @Deprecated public void setHandlesParentData(boolean 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);
@@ -486,7 +481,6 @@
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
     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 isPlaced;
     property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -503,6 +497,8 @@
   }
 
   public enum LayoutNode.LayoutState {
+    method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutNode.LayoutState[] values();
     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;
@@ -584,7 +580,7 @@
     method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
     method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
     method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
-    field public static final androidx.ui.core.Modifier.Companion! Companion;
+    field public static final androidx.ui.core.Modifier.Companion Companion;
   }
 
   public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -634,12 +630,15 @@
     method public void drawLayer(androidx.ui.graphics.Canvas canvas);
     method public long getLayerId();
     method public android.graphics.Matrix getMatrix();
+    method public androidx.ui.core.DrawLayerModifier getModifier();
     method public void invalidate();
     method public void move(androidx.ui.unit.IntOffset position);
     method public void resize(androidx.ui.unit.IntSize size);
+    method public void setModifier(androidx.ui.core.DrawLayerModifier p);
     method public void updateDisplayList();
     method public void updateLayerProperties();
     property public abstract long layerId;
+    property public abstract androidx.ui.core.DrawLayerModifier modifier;
   }
 
   public interface Owner {
@@ -684,7 +683,7 @@
     property public abstract boolean showLayoutBounds;
     property public abstract androidx.ui.input.TextInputService textInputService;
     property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
-    field public static final androidx.ui.core.Owner.Companion! Companion;
+    field public static final androidx.ui.core.Owner.Companion Companion;
   }
 
   public static final class Owner.Companion {
@@ -734,6 +733,8 @@
   }
 
   public enum PointerEventPass {
+    method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.PointerEventPass[] values();
     enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -813,7 +814,6 @@
   }
 
   public final class TestTagKt {
-    method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
   }
 
@@ -826,7 +826,7 @@
     method public static float getPivotFractionY-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Immutable public static inline String! toString-impl(long p);
-    field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+    field public static final androidx.ui.core.TransformOrigin.Companion Companion;
   }
 
   public static final class TransformOrigin.Companion {
@@ -859,8 +859,8 @@
     method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
   }
 
   public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -889,6 +889,8 @@
 package androidx.ui.core.focus {
 
   public enum FocusDetailedState {
+    method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusDetailedState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -913,6 +915,8 @@
   }
 
   public enum FocusState {
+    method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusState Focused;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -962,7 +966,10 @@
   }
 
   public final class DragSlopExceededGestureFilterKt {
-    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+  }
+
+  @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
   }
 
   public final class GestureUtilsKt {
@@ -990,7 +997,7 @@
   }
 
   public final class RawDragGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
   }
 
   public final class RawPressStartGestureFilterKt {
@@ -1026,6 +1033,17 @@
   public final class ScaleUtilKt {
   }
 
+  public interface ScrollCallback {
+    method public default void onCancel();
+    method public default float onScroll(float scrollDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(float velocity);
+  }
+
+  public final class ScrollGestureFilterKt {
+    method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+  }
+
   public final class TapGestureFilterKt {
     method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
@@ -1045,13 +1063,36 @@
   }
 
   public enum DelayUpMessage {
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
   }
 
   public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
-    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+  }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+  public enum Orientation {
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+  }
+
+  @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+    ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+    method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public void onCancel();
+    method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
   }
 
 }
@@ -1080,6 +1121,8 @@
   }
 
   public enum HapticFeedbackType {
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
   }
@@ -1113,7 +1156,7 @@
     method public int getKeyCode();
     method public static inline int hashCode-impl(int p);
     method public static String toString-impl(int $this);
-    field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+    field public static final androidx.ui.core.keyinput.Key.Companion Companion;
   }
 
   public static final class Key.Companion {
@@ -1706,6 +1749,8 @@
   }
 
   public enum KeyEventType {
+    method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.keyinput.KeyEventType[] values();
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
   }
@@ -1789,6 +1834,9 @@
   public final class SelectionHandlesKt {
   }
 
+  public final class SelectionLayoutKt {
+  }
+
   public final class SelectionManagerKt {
   }
 
@@ -1838,19 +1886,18 @@
   }
 
   public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
-    method public boolean getApplyToChildLayoutNode();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
-    property public abstract boolean applyToChildLayoutNode;
     property public abstract int id;
     property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
   }
 
   public final class SemanticsModifierKt {
-    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
   }
 
   public final class SemanticsNode {
+    method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.unit.PxBounds getBoundsInRoot();
     method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
     method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1873,7 +1920,7 @@
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
     property public final androidx.ui.unit.IntSize size;
-    field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+    field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
   }
 
   public static final class SemanticsNode.Companion {
@@ -1907,6 +1954,8 @@
   }
 
   public enum TextToolbarStatus {
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
   }
@@ -1927,6 +1976,13 @@
     method public final void invalidate();
   }
 
+  public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+    ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+    method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+  }
+
   public final class VectorAsset {
     method public String component1();
     method public float component2();
@@ -1961,8 +2017,8 @@
   }
 
   public final class VectorComposeKt {
-    method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
-    method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+    method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
   }
 
   public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2015,7 +2071,7 @@
 
   public final class VectorPainterKt {
     method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
-    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
     field public static final String RootGroupName = "VectorRootGroup";
   }
 
@@ -2044,9 +2100,6 @@
     method public float getStrokeLineWidth();
   }
 
-  public final class VectorScope {
-  }
-
 }
 
 package androidx.ui.graphics.vector.compat {
@@ -2074,17 +2127,16 @@
   public final class PointerInteropUtilsKt {
   }
 
-  public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
-    ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
-    method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public android.content.Context getContext();
-    method public Object getRoot();
-  }
-
-  public final class UiComposerKt {
+  public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+    ctor public UiApplier(Object root);
+    method public void down(Object node);
+    method public Object getCurrent();
+    method public void insert(int index, Object instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+    method public void reset();
+    method public void up();
+    property public Object current;
   }
 
   public final class ViewInteropKt {
@@ -2209,11 +2261,7 @@
     property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
-    field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
-  }
-
-  public final class SemanticsKt {
-    method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
   }
 
   public final class SemanticsProperties {
@@ -2233,7 +2281,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
-    field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+    field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
   }
 
   public final class SemanticsPropertiesKt {
@@ -2329,6 +2377,11 @@
     method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
   }
 
+  public final class EmitViewKt {
+    method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+    method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+  }
+
 }
 
 package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
index 905873c..0e76587 100644
--- a/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -1,12 +1,4 @@
 // Signature format: 3.0
-package androidx.compose {
-
-  public final class ComposerCompatKt {
-    method @Deprecated public static androidx.ui.node.UiComposer getComposer();
-  }
-
-}
-
 package androidx.ui.autofill {
 
   public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
   }
 
   public enum AutofillType {
+    method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.autofill.AutofillType[] values();
     enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
   @androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
     method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
-    field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+    field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
   }
 
   public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
 
   @androidx.compose.Immutable public interface Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
-    field public static final androidx.ui.core.Alignment.Companion! Companion;
+    field public static final androidx.ui.core.Alignment.Companion Companion;
   }
 
   public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class AlignmentLine {
-    field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+    field public static final androidx.ui.core.AlignmentLine.Companion Companion;
     field public static final int Unspecified = -2147483648; // 0x80000000
   }
 
@@ -256,7 +250,7 @@
 
   @androidx.compose.Stable public interface ContentScale {
     method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
-    field public static final androidx.ui.core.ContentScale.Companion! Companion;
+    field public static final androidx.ui.core.ContentScale.Companion Companion;
   }
 
   public static final class ContentScale.Companion {
@@ -291,6 +285,8 @@
   }
 
   public enum Direction {
+    method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.Direction[] values();
     enum_constant public static final androidx.ui.core.Direction DOWN;
     enum_constant public static final androidx.ui.core.Direction LEFT;
     enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -343,6 +339,8 @@
   }
 
   public enum DropDownAlignment {
+    method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.DropDownAlignment[] values();
     enum_constant public static final androidx.ui.core.DropDownAlignment End;
     enum_constant public static final androidx.ui.core.DropDownAlignment Start;
   }
@@ -424,7 +422,6 @@
     method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
-    method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
   }
 
@@ -446,7 +443,6 @@
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
     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.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -477,7 +473,6 @@
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
     method public void setDepth(int p);
-    method @Deprecated public void setHandlesParentData(boolean 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);
@@ -487,7 +482,6 @@
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
     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 isPlaced;
     property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -504,6 +498,8 @@
   }
 
   public enum LayoutNode.LayoutState {
+    method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutNode.LayoutState[] values();
     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;
@@ -585,7 +581,7 @@
     method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
     method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
     method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
-    field public static final androidx.ui.core.Modifier.Companion! Companion;
+    field public static final androidx.ui.core.Modifier.Companion Companion;
   }
 
   public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -635,12 +631,15 @@
     method public void drawLayer(androidx.ui.graphics.Canvas canvas);
     method public long getLayerId();
     method public android.graphics.Matrix getMatrix();
+    method public androidx.ui.core.DrawLayerModifier getModifier();
     method public void invalidate();
     method public void move(androidx.ui.unit.IntOffset position);
     method public void resize(androidx.ui.unit.IntSize size);
+    method public void setModifier(androidx.ui.core.DrawLayerModifier p);
     method public void updateDisplayList();
     method public void updateLayerProperties();
     property public abstract long layerId;
+    property public abstract androidx.ui.core.DrawLayerModifier modifier;
   }
 
   public interface Owner {
@@ -686,7 +685,7 @@
     property public abstract boolean showLayoutBounds;
     property public abstract androidx.ui.input.TextInputService textInputService;
     property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
-    field public static final androidx.ui.core.Owner.Companion! Companion;
+    field public static final androidx.ui.core.Owner.Companion Companion;
   }
 
   public static final class Owner.Companion {
@@ -736,6 +735,8 @@
   }
 
   public enum PointerEventPass {
+    method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.PointerEventPass[] values();
     enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -815,7 +816,6 @@
   }
 
   public final class TestTagKt {
-    method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
   }
 
@@ -828,7 +828,7 @@
     method public static float getPivotFractionY-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Immutable public static inline String! toString-impl(long p);
-    field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+    field public static final androidx.ui.core.TransformOrigin.Companion Companion;
   }
 
   public static final class TransformOrigin.Companion {
@@ -861,8 +861,8 @@
     method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
   }
 
   public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -891,6 +891,8 @@
 package androidx.ui.core.focus {
 
   public enum FocusDetailedState {
+    method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusDetailedState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -915,6 +917,8 @@
   }
 
   public enum FocusState {
+    method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusState Focused;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -964,7 +968,10 @@
   }
 
   public final class DragSlopExceededGestureFilterKt {
-    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+  }
+
+  @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
   }
 
   public final class GestureUtilsKt {
@@ -992,7 +999,7 @@
   }
 
   public final class RawDragGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
   }
 
   public final class RawPressStartGestureFilterKt {
@@ -1028,6 +1035,17 @@
   public final class ScaleUtilKt {
   }
 
+  public interface ScrollCallback {
+    method public default void onCancel();
+    method public default float onScroll(float scrollDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(float velocity);
+  }
+
+  public final class ScrollGestureFilterKt {
+    method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+  }
+
   public final class TapGestureFilterKt {
     method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
@@ -1047,13 +1065,36 @@
   }
 
   public enum DelayUpMessage {
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
   }
 
   public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
-    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+  }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+  public enum Orientation {
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+  }
+
+  @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+    ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+    method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public void onCancel();
+    method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
   }
 
 }
@@ -1082,6 +1123,8 @@
   }
 
   public enum HapticFeedbackType {
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
   }
@@ -1115,7 +1158,7 @@
     method public int getKeyCode();
     method public static inline int hashCode-impl(int p);
     method public static String toString-impl(int $this);
-    field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+    field public static final androidx.ui.core.keyinput.Key.Companion Companion;
   }
 
   public static final class Key.Companion {
@@ -1708,6 +1751,8 @@
   }
 
   public enum KeyEventType {
+    method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.keyinput.KeyEventType[] values();
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
   }
@@ -1791,6 +1836,9 @@
   public final class SelectionHandlesKt {
   }
 
+  public final class SelectionLayoutKt {
+  }
+
   public final class SelectionManagerKt {
   }
 
@@ -1840,19 +1888,18 @@
   }
 
   public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
-    method public boolean getApplyToChildLayoutNode();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
-    property public abstract boolean applyToChildLayoutNode;
     property public abstract int id;
     property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
   }
 
   public final class SemanticsModifierKt {
-    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
   }
 
   public final class SemanticsNode {
+    method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.unit.PxBounds getBoundsInRoot();
     method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
     method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1875,7 +1922,7 @@
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
     property public final androidx.ui.unit.IntSize size;
-    field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+    field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
   }
 
   public static final class SemanticsNode.Companion {
@@ -1909,6 +1956,8 @@
   }
 
   public enum TextToolbarStatus {
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
   }
@@ -1929,6 +1978,13 @@
     method public final void invalidate();
   }
 
+  public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+    ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+    method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+  }
+
   public final class VectorAsset {
     method public String component1();
     method public float component2();
@@ -1963,8 +2019,8 @@
   }
 
   public final class VectorComposeKt {
-    method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
-    method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+    method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
   }
 
   public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2017,7 +2073,7 @@
 
   public final class VectorPainterKt {
     method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
-    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
     field public static final String RootGroupName = "VectorRootGroup";
   }
 
@@ -2046,9 +2102,6 @@
     method public float getStrokeLineWidth();
   }
 
-  public final class VectorScope {
-  }
-
 }
 
 package androidx.ui.graphics.vector.compat {
@@ -2076,17 +2129,16 @@
   public final class PointerInteropUtilsKt {
   }
 
-  public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
-    ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
-    method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public android.content.Context getContext();
-    method public Object getRoot();
-  }
-
-  public final class UiComposerKt {
+  public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+    ctor public UiApplier(Object root);
+    method public void down(Object node);
+    method public Object getCurrent();
+    method public void insert(int index, Object instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+    method public void reset();
+    method public void up();
+    property public Object current;
   }
 
   public final class ViewInteropKt {
@@ -2211,11 +2263,7 @@
     property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
-    field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
-  }
-
-  public final class SemanticsKt {
-    method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
   }
 
   public final class SemanticsProperties {
@@ -2235,7 +2283,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
-    field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+    field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
   }
 
   public final class SemanticsPropertiesKt {
@@ -2331,6 +2379,11 @@
     method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
   }
 
+  public final class EmitViewKt {
+    method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+    method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+  }
+
 }
 
 package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/public_plus_experimental_current.txt b/ui/ui-core/api/public_plus_experimental_current.txt
index 905873c..0e76587 100644
--- a/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-core/api/public_plus_experimental_current.txt
@@ -1,12 +1,4 @@
 // Signature format: 3.0
-package androidx.compose {
-
-  public final class ComposerCompatKt {
-    method @Deprecated public static androidx.ui.node.UiComposer getComposer();
-  }
-
-}
-
 package androidx.ui.autofill {
 
   public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
   }
 
   public enum AutofillType {
+    method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.autofill.AutofillType[] values();
     enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
   @androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
     method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
-    field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+    field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
   }
 
   public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
 
   @androidx.compose.Immutable public interface Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
-    field public static final androidx.ui.core.Alignment.Companion! Companion;
+    field public static final androidx.ui.core.Alignment.Companion Companion;
   }
 
   public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class AlignmentLine {
-    field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+    field public static final androidx.ui.core.AlignmentLine.Companion Companion;
     field public static final int Unspecified = -2147483648; // 0x80000000
   }
 
@@ -256,7 +250,7 @@
 
   @androidx.compose.Stable public interface ContentScale {
     method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
-    field public static final androidx.ui.core.ContentScale.Companion! Companion;
+    field public static final androidx.ui.core.ContentScale.Companion Companion;
   }
 
   public static final class ContentScale.Companion {
@@ -291,6 +285,8 @@
   }
 
   public enum Direction {
+    method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.Direction[] values();
     enum_constant public static final androidx.ui.core.Direction DOWN;
     enum_constant public static final androidx.ui.core.Direction LEFT;
     enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -343,6 +339,8 @@
   }
 
   public enum DropDownAlignment {
+    method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.DropDownAlignment[] values();
     enum_constant public static final androidx.ui.core.DropDownAlignment End;
     enum_constant public static final androidx.ui.core.DropDownAlignment Start;
   }
@@ -424,7 +422,6 @@
     method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
-    method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
   }
 
@@ -446,7 +443,6 @@
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
     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.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -477,7 +473,6 @@
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
     method public void setDepth(int p);
-    method @Deprecated public void setHandlesParentData(boolean 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);
@@ -487,7 +482,6 @@
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
     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 isPlaced;
     property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -504,6 +498,8 @@
   }
 
   public enum LayoutNode.LayoutState {
+    method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutNode.LayoutState[] values();
     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;
@@ -585,7 +581,7 @@
     method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
     method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
     method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
-    field public static final androidx.ui.core.Modifier.Companion! Companion;
+    field public static final androidx.ui.core.Modifier.Companion Companion;
   }
 
   public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -635,12 +631,15 @@
     method public void drawLayer(androidx.ui.graphics.Canvas canvas);
     method public long getLayerId();
     method public android.graphics.Matrix getMatrix();
+    method public androidx.ui.core.DrawLayerModifier getModifier();
     method public void invalidate();
     method public void move(androidx.ui.unit.IntOffset position);
     method public void resize(androidx.ui.unit.IntSize size);
+    method public void setModifier(androidx.ui.core.DrawLayerModifier p);
     method public void updateDisplayList();
     method public void updateLayerProperties();
     property public abstract long layerId;
+    property public abstract androidx.ui.core.DrawLayerModifier modifier;
   }
 
   public interface Owner {
@@ -686,7 +685,7 @@
     property public abstract boolean showLayoutBounds;
     property public abstract androidx.ui.input.TextInputService textInputService;
     property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
-    field public static final androidx.ui.core.Owner.Companion! Companion;
+    field public static final androidx.ui.core.Owner.Companion Companion;
   }
 
   public static final class Owner.Companion {
@@ -736,6 +735,8 @@
   }
 
   public enum PointerEventPass {
+    method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.PointerEventPass[] values();
     enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -815,7 +816,6 @@
   }
 
   public final class TestTagKt {
-    method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
   }
 
@@ -828,7 +828,7 @@
     method public static float getPivotFractionY-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Immutable public static inline String! toString-impl(long p);
-    field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+    field public static final androidx.ui.core.TransformOrigin.Companion Companion;
   }
 
   public static final class TransformOrigin.Companion {
@@ -861,8 +861,8 @@
     method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
   }
 
   public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -891,6 +891,8 @@
 package androidx.ui.core.focus {
 
   public enum FocusDetailedState {
+    method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusDetailedState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -915,6 +917,8 @@
   }
 
   public enum FocusState {
+    method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusState Focused;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -964,7 +968,10 @@
   }
 
   public final class DragSlopExceededGestureFilterKt {
-    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+  }
+
+  @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
   }
 
   public final class GestureUtilsKt {
@@ -992,7 +999,7 @@
   }
 
   public final class RawDragGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
   }
 
   public final class RawPressStartGestureFilterKt {
@@ -1028,6 +1035,17 @@
   public final class ScaleUtilKt {
   }
 
+  public interface ScrollCallback {
+    method public default void onCancel();
+    method public default float onScroll(float scrollDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(float velocity);
+  }
+
+  public final class ScrollGestureFilterKt {
+    method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+  }
+
   public final class TapGestureFilterKt {
     method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
@@ -1047,13 +1065,36 @@
   }
 
   public enum DelayUpMessage {
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
   }
 
   public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
-    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+  }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+  public enum Orientation {
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+  }
+
+  @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+    ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+    method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public void onCancel();
+    method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
   }
 
 }
@@ -1082,6 +1123,8 @@
   }
 
   public enum HapticFeedbackType {
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
   }
@@ -1115,7 +1158,7 @@
     method public int getKeyCode();
     method public static inline int hashCode-impl(int p);
     method public static String toString-impl(int $this);
-    field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+    field public static final androidx.ui.core.keyinput.Key.Companion Companion;
   }
 
   public static final class Key.Companion {
@@ -1708,6 +1751,8 @@
   }
 
   public enum KeyEventType {
+    method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.keyinput.KeyEventType[] values();
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
   }
@@ -1791,6 +1836,9 @@
   public final class SelectionHandlesKt {
   }
 
+  public final class SelectionLayoutKt {
+  }
+
   public final class SelectionManagerKt {
   }
 
@@ -1840,19 +1888,18 @@
   }
 
   public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
-    method public boolean getApplyToChildLayoutNode();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
-    property public abstract boolean applyToChildLayoutNode;
     property public abstract int id;
     property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
   }
 
   public final class SemanticsModifierKt {
-    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
   }
 
   public final class SemanticsNode {
+    method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.unit.PxBounds getBoundsInRoot();
     method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
     method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1875,7 +1922,7 @@
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
     property public final androidx.ui.unit.IntSize size;
-    field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+    field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
   }
 
   public static final class SemanticsNode.Companion {
@@ -1909,6 +1956,8 @@
   }
 
   public enum TextToolbarStatus {
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
   }
@@ -1929,6 +1978,13 @@
     method public final void invalidate();
   }
 
+  public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+    ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+    method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+  }
+
   public final class VectorAsset {
     method public String component1();
     method public float component2();
@@ -1963,8 +2019,8 @@
   }
 
   public final class VectorComposeKt {
-    method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
-    method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+    method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
   }
 
   public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2017,7 +2073,7 @@
 
   public final class VectorPainterKt {
     method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
-    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
     field public static final String RootGroupName = "VectorRootGroup";
   }
 
@@ -2046,9 +2102,6 @@
     method public float getStrokeLineWidth();
   }
 
-  public final class VectorScope {
-  }
-
 }
 
 package androidx.ui.graphics.vector.compat {
@@ -2076,17 +2129,16 @@
   public final class PointerInteropUtilsKt {
   }
 
-  public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
-    ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
-    method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public android.content.Context getContext();
-    method public Object getRoot();
-  }
-
-  public final class UiComposerKt {
+  public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+    ctor public UiApplier(Object root);
+    method public void down(Object node);
+    method public Object getCurrent();
+    method public void insert(int index, Object instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+    method public void reset();
+    method public void up();
+    property public Object current;
   }
 
   public final class ViewInteropKt {
@@ -2211,11 +2263,7 @@
     property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
-    field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
-  }
-
-  public final class SemanticsKt {
-    method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
   }
 
   public final class SemanticsProperties {
@@ -2235,7 +2283,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
-    field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+    field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
   }
 
   public final class SemanticsPropertiesKt {
@@ -2331,6 +2379,11 @@
     method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
   }
 
+  public final class EmitViewKt {
+    method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+    method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+  }
+
 }
 
 package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/restricted_0.1.0-dev15.txt b/ui/ui-core/api/restricted_0.1.0-dev15.txt
index 2f45773..97e1ad4d 100644
--- a/ui/ui-core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-core/api/restricted_0.1.0-dev15.txt
@@ -1,12 +1,4 @@
 // Signature format: 3.0
-package androidx.compose {
-
-  public final class ComposerCompatKt {
-    method @Deprecated public static androidx.ui.node.UiComposer getComposer();
-  }
-
-}
-
 package androidx.ui.autofill {
 
   public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
   }
 
   public enum AutofillType {
+    method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.autofill.AutofillType[] values();
     enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
   @androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
     method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
-    field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+    field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
   }
 
   public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
 
   @androidx.compose.Immutable public interface Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
-    field public static final androidx.ui.core.Alignment.Companion! Companion;
+    field public static final androidx.ui.core.Alignment.Companion Companion;
   }
 
   public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class AlignmentLine {
-    field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+    field public static final androidx.ui.core.AlignmentLine.Companion Companion;
     field public static final int Unspecified = -2147483648; // 0x80000000
   }
 
@@ -262,7 +256,7 @@
 
   @androidx.compose.Stable public interface ContentScale {
     method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
-    field public static final androidx.ui.core.ContentScale.Companion! Companion;
+    field public static final androidx.ui.core.ContentScale.Companion Companion;
   }
 
   public static final class ContentScale.Companion {
@@ -311,6 +305,8 @@
   }
 
   public enum Direction {
+    method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.Direction[] values();
     enum_constant public static final androidx.ui.core.Direction DOWN;
     enum_constant public static final androidx.ui.core.Direction LEFT;
     enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -363,6 +359,8 @@
   }
 
   public enum DropDownAlignment {
+    method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.DropDownAlignment[] values();
     enum_constant public static final androidx.ui.core.DropDownAlignment End;
     enum_constant public static final androidx.ui.core.DropDownAlignment Start;
   }
@@ -402,11 +400,15 @@
   }
 
   @kotlin.PublishedApi internal enum IntrinsicMinMax {
+    method public static androidx.ui.core.IntrinsicMinMax valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.IntrinsicMinMax[] values();
     enum_constant public static final androidx.ui.core.IntrinsicMinMax Max;
     enum_constant public static final androidx.ui.core.IntrinsicMinMax Min;
   }
 
   @kotlin.PublishedApi internal enum IntrinsicWidthHeight {
+    method public static androidx.ui.core.IntrinsicWidthHeight valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.IntrinsicWidthHeight[] values();
     enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Height;
     enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Width;
   }
@@ -472,7 +474,6 @@
     method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
-    method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
   }
 
@@ -494,7 +495,6 @@
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
     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.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -525,7 +525,6 @@
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
     method public void setDepth(int p);
-    method @Deprecated public void setHandlesParentData(boolean 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);
@@ -535,7 +534,6 @@
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
     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 isPlaced;
     property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -552,6 +550,8 @@
   }
 
   public enum LayoutNode.LayoutState {
+    method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutNode.LayoutState[] values();
     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;
@@ -635,7 +635,7 @@
     method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
     method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
     method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
-    field public static final androidx.ui.core.Modifier.Companion! Companion;
+    field public static final androidx.ui.core.Modifier.Companion Companion;
   }
 
   public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -685,12 +685,15 @@
     method public void drawLayer(androidx.ui.graphics.Canvas canvas);
     method public long getLayerId();
     method public android.graphics.Matrix getMatrix();
+    method public androidx.ui.core.DrawLayerModifier getModifier();
     method public void invalidate();
     method public void move(androidx.ui.unit.IntOffset position);
     method public void resize(androidx.ui.unit.IntSize size);
+    method public void setModifier(androidx.ui.core.DrawLayerModifier p);
     method public void updateDisplayList();
     method public void updateLayerProperties();
     property public abstract long layerId;
+    property public abstract androidx.ui.core.DrawLayerModifier modifier;
   }
 
   public interface Owner {
@@ -736,7 +739,7 @@
     property public abstract boolean showLayoutBounds;
     property public abstract androidx.ui.input.TextInputService textInputService;
     property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
-    field public static final androidx.ui.core.Owner.Companion! Companion;
+    field public static final androidx.ui.core.Owner.Companion Companion;
   }
 
   public static final class Owner.Companion {
@@ -786,6 +789,8 @@
   }
 
   public enum PointerEventPass {
+    method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.PointerEventPass[] values();
     enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -865,7 +870,6 @@
   }
 
   public final class TestTagKt {
-    method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
   }
 
@@ -878,7 +882,7 @@
     method public static float getPivotFractionY-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Immutable public static inline String! toString-impl(long p);
-    field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+    field public static final androidx.ui.core.TransformOrigin.Companion Companion;
   }
 
   public static final class TransformOrigin.Companion {
@@ -911,8 +915,8 @@
     method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
   }
 
   public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -941,6 +945,8 @@
 package androidx.ui.core.focus {
 
   public enum FocusDetailedState {
+    method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusDetailedState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -965,6 +971,8 @@
   }
 
   public enum FocusState {
+    method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusState Focused;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -1014,7 +1022,10 @@
   }
 
   public final class DragSlopExceededGestureFilterKt {
-    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+  }
+
+  @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
   }
 
   public final class GestureUtilsKt {
@@ -1042,7 +1053,7 @@
   }
 
   public final class RawDragGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
   }
 
   public final class RawPressStartGestureFilterKt {
@@ -1078,6 +1089,17 @@
   public final class ScaleUtilKt {
   }
 
+  public interface ScrollCallback {
+    method public default void onCancel();
+    method public default float onScroll(float scrollDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(float velocity);
+  }
+
+  public final class ScrollGestureFilterKt {
+    method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+  }
+
   public final class TapGestureFilterKt {
     method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
@@ -1097,13 +1119,36 @@
   }
 
   public enum DelayUpMessage {
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
   }
 
   public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
-    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+  }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+  public enum Orientation {
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+  }
+
+  @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+    ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+    method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public void onCancel();
+    method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
   }
 
 }
@@ -1132,6 +1177,8 @@
   }
 
   public enum HapticFeedbackType {
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
   }
@@ -1165,7 +1212,7 @@
     method public int getKeyCode();
     method public static inline int hashCode-impl(int p);
     method public static String toString-impl(int $this);
-    field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+    field public static final androidx.ui.core.keyinput.Key.Companion Companion;
   }
 
   public static final class Key.Companion {
@@ -1758,6 +1805,8 @@
   }
 
   public enum KeyEventType {
+    method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.keyinput.KeyEventType[] values();
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
   }
@@ -1841,6 +1890,9 @@
   public final class SelectionHandlesKt {
   }
 
+  public final class SelectionLayoutKt {
+  }
+
   public final class SelectionManagerKt {
   }
 
@@ -1890,19 +1942,18 @@
   }
 
   public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
-    method public boolean getApplyToChildLayoutNode();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
-    property public abstract boolean applyToChildLayoutNode;
     property public abstract int id;
     property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
   }
 
   public final class SemanticsModifierKt {
-    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
   }
 
   public final class SemanticsNode {
+    method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.unit.PxBounds getBoundsInRoot();
     method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
     method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1925,7 +1976,7 @@
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
     property public final androidx.ui.unit.IntSize size;
-    field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+    field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
   }
 
   public static final class SemanticsNode.Companion {
@@ -1959,6 +2010,8 @@
   }
 
   public enum TextToolbarStatus {
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
   }
@@ -1979,6 +2032,13 @@
     method public final void invalidate();
   }
 
+  public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+    ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+    method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+  }
+
   public final class VectorAsset {
     method public String component1();
     method public float component2();
@@ -2013,8 +2073,8 @@
   }
 
   public final class VectorComposeKt {
-    method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
-    method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+    method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
   }
 
   public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2067,7 +2127,7 @@
 
   public final class VectorPainterKt {
     method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
-    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
     field public static final String RootGroupName = "VectorRootGroup";
   }
 
@@ -2096,9 +2156,6 @@
     method public float getStrokeLineWidth();
   }
 
-  public final class VectorScope {
-  }
-
 }
 
 package androidx.ui.graphics.vector.compat {
@@ -2126,17 +2183,16 @@
   public final class PointerInteropUtilsKt {
   }
 
-  public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
-    ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
-    method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public android.content.Context getContext();
-    method public Object getRoot();
-  }
-
-  public final class UiComposerKt {
+  public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+    ctor public UiApplier(Object root);
+    method public void down(Object node);
+    method public Object getCurrent();
+    method public void insert(int index, Object instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+    method public void reset();
+    method public void up();
+    property public Object current;
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public interface ViewAdapter {
@@ -2270,11 +2326,7 @@
     property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
-    field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
-  }
-
-  public final class SemanticsKt {
-    method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
   }
 
   public final class SemanticsProperties {
@@ -2294,7 +2346,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
-    field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+    field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
   }
 
   public final class SemanticsPropertiesKt {
@@ -2390,6 +2442,11 @@
     method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
   }
 
+  public final class EmitViewKt {
+    method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+    method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+  }
+
 }
 
 package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/restricted_current.txt b/ui/ui-core/api/restricted_current.txt
index 2f45773..97e1ad4d 100644
--- a/ui/ui-core/api/restricted_current.txt
+++ b/ui/ui-core/api/restricted_current.txt
@@ -1,12 +1,4 @@
 // Signature format: 3.0
-package androidx.compose {
-
-  public final class ComposerCompatKt {
-    method @Deprecated public static androidx.ui.node.UiComposer getComposer();
-  }
-
-}
-
 package androidx.ui.autofill {
 
   public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
   }
 
   public enum AutofillType {
+    method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.autofill.AutofillType[] values();
     enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
     enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
   @androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
     method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
-    field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+    field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
   }
 
   public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
 
   @androidx.compose.Immutable public interface Alignment {
     method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
-    field public static final androidx.ui.core.Alignment.Companion! Companion;
+    field public static final androidx.ui.core.Alignment.Companion Companion;
   }
 
   public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class AlignmentLine {
-    field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+    field public static final androidx.ui.core.AlignmentLine.Companion Companion;
     field public static final int Unspecified = -2147483648; // 0x80000000
   }
 
@@ -262,7 +256,7 @@
 
   @androidx.compose.Stable public interface ContentScale {
     method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
-    field public static final androidx.ui.core.ContentScale.Companion! Companion;
+    field public static final androidx.ui.core.ContentScale.Companion Companion;
   }
 
   public static final class ContentScale.Companion {
@@ -311,6 +305,8 @@
   }
 
   public enum Direction {
+    method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.Direction[] values();
     enum_constant public static final androidx.ui.core.Direction DOWN;
     enum_constant public static final androidx.ui.core.Direction LEFT;
     enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -363,6 +359,8 @@
   }
 
   public enum DropDownAlignment {
+    method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.DropDownAlignment[] values();
     enum_constant public static final androidx.ui.core.DropDownAlignment End;
     enum_constant public static final androidx.ui.core.DropDownAlignment Start;
   }
@@ -402,11 +400,15 @@
   }
 
   @kotlin.PublishedApi internal enum IntrinsicMinMax {
+    method public static androidx.ui.core.IntrinsicMinMax valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.IntrinsicMinMax[] values();
     enum_constant public static final androidx.ui.core.IntrinsicMinMax Max;
     enum_constant public static final androidx.ui.core.IntrinsicMinMax Min;
   }
 
   @kotlin.PublishedApi internal enum IntrinsicWidthHeight {
+    method public static androidx.ui.core.IntrinsicWidthHeight valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.IntrinsicWidthHeight[] values();
     enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Height;
     enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Width;
   }
@@ -472,7 +474,6 @@
     method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
     method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
-    method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
   }
 
@@ -494,7 +495,6 @@
     method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
     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.LayoutNode.LayoutState getLayoutState();
     method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -525,7 +525,6 @@
     method public void requestRemeasure();
     method @Deprecated public void setCanMultiMeasure(boolean p);
     method public void setDepth(int p);
-    method @Deprecated public void setHandlesParentData(boolean 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);
@@ -535,7 +534,6 @@
     property public final java.util.List<androidx.ui.core.LayoutNode> children;
     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 isPlaced;
     property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -552,6 +550,8 @@
   }
 
   public enum LayoutNode.LayoutState {
+    method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutNode.LayoutState[] values();
     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;
@@ -635,7 +635,7 @@
     method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
     method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
     method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
-    field public static final androidx.ui.core.Modifier.Companion! Companion;
+    field public static final androidx.ui.core.Modifier.Companion Companion;
   }
 
   public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -685,12 +685,15 @@
     method public void drawLayer(androidx.ui.graphics.Canvas canvas);
     method public long getLayerId();
     method public android.graphics.Matrix getMatrix();
+    method public androidx.ui.core.DrawLayerModifier getModifier();
     method public void invalidate();
     method public void move(androidx.ui.unit.IntOffset position);
     method public void resize(androidx.ui.unit.IntSize size);
+    method public void setModifier(androidx.ui.core.DrawLayerModifier p);
     method public void updateDisplayList();
     method public void updateLayerProperties();
     property public abstract long layerId;
+    property public abstract androidx.ui.core.DrawLayerModifier modifier;
   }
 
   public interface Owner {
@@ -736,7 +739,7 @@
     property public abstract boolean showLayoutBounds;
     property public abstract androidx.ui.input.TextInputService textInputService;
     property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
-    field public static final androidx.ui.core.Owner.Companion! Companion;
+    field public static final androidx.ui.core.Owner.Companion Companion;
   }
 
   public static final class Owner.Companion {
@@ -786,6 +789,8 @@
   }
 
   public enum PointerEventPass {
+    method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.PointerEventPass[] values();
     enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
     enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -865,7 +870,6 @@
   }
 
   public final class TestTagKt {
-    method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
   }
 
@@ -878,7 +882,7 @@
     method public static float getPivotFractionY-impl(long $this);
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method @androidx.compose.Immutable public static inline String! toString-impl(long p);
-    field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+    field public static final androidx.ui.core.TransformOrigin.Companion Companion;
   }
 
   public static final class TransformOrigin.Companion {
@@ -911,8 +915,8 @@
     method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
     method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
-    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
   }
 
   public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -941,6 +945,8 @@
 package androidx.ui.core.focus {
 
   public enum FocusDetailedState {
+    method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusDetailedState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
     enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -965,6 +971,8 @@
   }
 
   public enum FocusState {
+    method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.focus.FocusState[] values();
     enum_constant public static final androidx.ui.core.focus.FocusState Focused;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
     enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -1014,7 +1022,10 @@
   }
 
   public final class DragSlopExceededGestureFilterKt {
-    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+    method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+  }
+
+  @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
   }
 
   public final class GestureUtilsKt {
@@ -1042,7 +1053,7 @@
   }
 
   public final class RawDragGestureFilterKt {
-    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+    method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
   }
 
   public final class RawPressStartGestureFilterKt {
@@ -1078,6 +1089,17 @@
   public final class ScaleUtilKt {
   }
 
+  public interface ScrollCallback {
+    method public default void onCancel();
+    method public default float onScroll(float scrollDistance);
+    method public default void onStart(androidx.ui.geometry.Offset downPosition);
+    method public default void onStop(float velocity);
+  }
+
+  public final class ScrollGestureFilterKt {
+    method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+  }
+
   public final class TapGestureFilterKt {
     method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
   }
@@ -1097,13 +1119,36 @@
   }
 
   public enum DelayUpMessage {
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
     enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
   }
 
   public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
-    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+    field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+  }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+  public enum Orientation {
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+    enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+  }
+
+  @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+    ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+    method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+    method public void onCancel();
+    method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+    method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
   }
 
 }
@@ -1132,6 +1177,8 @@
   }
 
   public enum HapticFeedbackType {
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
     enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
   }
@@ -1165,7 +1212,7 @@
     method public int getKeyCode();
     method public static inline int hashCode-impl(int p);
     method public static String toString-impl(int $this);
-    field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+    field public static final androidx.ui.core.keyinput.Key.Companion Companion;
   }
 
   public static final class Key.Companion {
@@ -1758,6 +1805,8 @@
   }
 
   public enum KeyEventType {
+    method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.keyinput.KeyEventType[] values();
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
     enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
   }
@@ -1841,6 +1890,9 @@
   public final class SelectionHandlesKt {
   }
 
+  public final class SelectionLayoutKt {
+  }
+
   public final class SelectionManagerKt {
   }
 
@@ -1890,19 +1942,18 @@
   }
 
   public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
-    method public boolean getApplyToChildLayoutNode();
     method public int getId();
     method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
-    property public abstract boolean applyToChildLayoutNode;
     property public abstract int id;
     property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
   }
 
   public final class SemanticsModifierKt {
-    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+    method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
   }
 
   public final class SemanticsNode {
+    method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
     method public androidx.ui.unit.PxBounds getBoundsInRoot();
     method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
     method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1925,7 +1976,7 @@
     property public final boolean isRoot;
     property public final androidx.ui.core.semantics.SemanticsNode? parent;
     property public final androidx.ui.unit.IntSize size;
-    field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+    field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
   }
 
   public static final class SemanticsNode.Companion {
@@ -1959,6 +2010,8 @@
   }
 
   public enum TextToolbarStatus {
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
     enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
   }
@@ -1979,6 +2032,13 @@
     method public final void invalidate();
   }
 
+  public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+    ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+    method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+  }
+
   public final class VectorAsset {
     method public String component1();
     method public float component2();
@@ -2013,8 +2073,8 @@
   }
 
   public final class VectorComposeKt {
-    method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
-    method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+    method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
   }
 
   public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2067,7 +2127,7 @@
 
   public final class VectorPainterKt {
     method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
-    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+    method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
     field public static final String RootGroupName = "VectorRootGroup";
   }
 
@@ -2096,9 +2156,6 @@
     method public float getStrokeLineWidth();
   }
 
-  public final class VectorScope {
-  }
-
 }
 
 package androidx.ui.graphics.vector.compat {
@@ -2126,17 +2183,16 @@
   public final class PointerInteropUtilsKt {
   }
 
-  public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
-    ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
-    method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
-    method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
-    method public android.content.Context getContext();
-    method public Object getRoot();
-  }
-
-  public final class UiComposerKt {
+  public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+    ctor public UiApplier(Object root);
+    method public void down(Object node);
+    method public Object getCurrent();
+    method public void insert(int index, Object instance);
+    method public void move(int from, int to, int count);
+    method public void remove(int index, int count);
+    method public void reset();
+    method public void up();
+    property public Object current;
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public interface ViewAdapter {
@@ -2270,11 +2326,7 @@
     property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
-    field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
-  }
-
-  public final class SemanticsKt {
-    method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
   }
 
   public final class SemanticsProperties {
@@ -2294,7 +2346,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
-    field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+    field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
   }
 
   public final class SemanticsPropertiesKt {
@@ -2390,6 +2442,11 @@
     method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
   }
 
+  public final class EmitViewKt {
+    method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+    method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+  }
+
 }
 
 package androidx.ui.viewmodel {
diff --git a/ui/ui-core/build.gradle b/ui/ui-core/build.gradle
index a936d8d..67d44ad 100644
--- a/ui/ui-core/build.gradle
+++ b/ui/ui-core/build.gradle
@@ -124,7 +124,9 @@
     testOptions.unitTests.includeAndroidResources = true
 }
 
-// An ugly hack to workaround bug in MPP Kotlin Gradle plugin.
+// An ugly hack to workaround b/159426957 causing MPP+AGP to conflict.
+// See also: https://youtrack.jetbrains.com/issue/KT-34650
+// See also: https://youtrack.jetbrains.com/issue/KT-39712
 afterEvaluate {
     ["Api", "Implementation", "CompileOnly", "RuntimeOnly"].each { scope ->
         def erroneousExtendsFrom = [
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
index 3fbfa70..6420041 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
@@ -20,21 +20,23 @@
 import androidx.ui.core.demos.focus.FocusableDemo
 import androidx.ui.core.demos.gestures.DoubleTapGestureFilterDemo
 import androidx.ui.core.demos.gestures.DoubleTapInTapDemo
-import androidx.ui.core.demos.gestures.DragAndScaleGestureDetectorDemo
+import androidx.ui.core.demos.gestures.DragAndScaleGestureFilterDemo
+import androidx.ui.core.demos.gestures.DragGestureFilterDemo
 import androidx.ui.core.demos.gestures.DragSlopExceededGestureFilterDemo
-import androidx.ui.core.demos.gestures.LongPressGestureDetectorDemo
+import androidx.ui.core.demos.gestures.HorizontalScrollersInVerticalScrollersDemo
+import androidx.ui.core.demos.gestures.LongPressDragGestureFilterDemo
 import androidx.ui.core.demos.gestures.NestedLongPressDemo
 import androidx.ui.core.demos.gestures.NestedPressingDemo
 import androidx.ui.core.demos.gestures.NestedScalingDemo
 import androidx.ui.core.demos.gestures.NestedScrollingDemo
 import androidx.ui.core.demos.gestures.PopupDragDemo
 import androidx.ui.core.demos.gestures.PressIndicatorGestureFilterDemo
-import androidx.ui.core.demos.gestures.TapGestureFilterDemo
 import androidx.ui.core.demos.gestures.RawDragGestureFilterDemo
 import androidx.ui.core.demos.gestures.ScaleGestureFilterDemo
-import androidx.ui.core.demos.gestures.DragGestureFilterDemo
-import androidx.ui.core.demos.gestures.LongPressDragGestureFilterDemo
 import androidx.ui.core.demos.gestures.PointerInputDuringSubComp
+import androidx.ui.core.demos.gestures.ScrollGestureFilterDemo
+import androidx.ui.core.demos.gestures.TapGestureFilterDemo
+import androidx.ui.core.demos.gestures.VerticalScrollerInDrawerDemo
 import androidx.ui.core.demos.keyinput.KeyInputDemo
 import androidx.ui.core.demos.viewinterop.ViewInComposeDemo
 import androidx.ui.demos.common.ComposableDemo
@@ -45,7 +47,8 @@
         ComposableDemo("Press Indication") { PressIndicatorGestureFilterDemo() },
         ComposableDemo("Tap") { TapGestureFilterDemo() },
         ComposableDemo("Double Tap") { DoubleTapGestureFilterDemo() },
-        ComposableDemo("Long Press") { LongPressGestureDetectorDemo() },
+        ComposableDemo("Long Press") { ScrollGestureFilterDemo() },
+        ComposableDemo("Scroll") { DragGestureFilterDemo() },
         ComposableDemo("Drag") { DragGestureFilterDemo() },
         ComposableDemo("Long Press Drag") { LongPressDragGestureFilterDemo() },
         ComposableDemo("Scale") { ScaleGestureFilterDemo() }
@@ -57,9 +60,15 @@
     DemoCategory(
         "Combinations / Case Studies", listOf(
             ComposableDemo("Nested Pressing") { NestedPressingDemo() },
+            ComposableDemo("Horizontal Scrollers In Vertical Scroller") {
+                HorizontalScrollersInVerticalScrollersDemo()
+            },
+            ComposableDemo("Vertical Scroller in Nav Drawer") {
+                VerticalScrollerInDrawerDemo()
+            },
             ComposableDemo("Nested Scrolling") { NestedScrollingDemo() },
             ComposableDemo("Nested Scaling") { NestedScalingDemo() },
-            ComposableDemo("Drag and Scale") { DragAndScaleGestureDetectorDemo() },
+            ComposableDemo("Drag and Scale") { DragAndScaleGestureFilterDemo() },
             ComposableDemo("Popup Drag") { PopupDragDemo() },
             ComposableDemo("Double Tap in Tap") { DoubleTapInTapDemo() },
             ComposableDemo("Nested Long Press") { NestedLongPressDemo() },
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt
index 271aaf3..6d47a3a 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt
@@ -33,7 +33,6 @@
 import androidx.ui.graphics.vector.PathBuilder
 import androidx.ui.graphics.vector.PathData
 import androidx.ui.graphics.vector.VectorPainter
-import androidx.ui.graphics.vector.VectorScope
 import androidx.ui.layout.Column
 import androidx.ui.layout.preferredSize
 import androidx.ui.layout.wrapContentSize
@@ -108,7 +107,7 @@
 }
 
 @Composable
-private fun VectorScope.BackgroundPath(vectorWidth: Float, vectorHeight: Float) {
+private fun BackgroundPath(vectorWidth: Float, vectorHeight: Float) {
     val background = PathData {
         horizontalLineTo(vectorWidth)
         verticalLineTo(vectorHeight)
@@ -129,7 +128,7 @@
 }
 
 @Composable
-private fun VectorScope.Triangle() {
+private fun Triangle() {
     val length = 150.0f
     Path(
         fill = RadialGradient(
@@ -152,7 +151,7 @@
 }
 
 @Composable
-private fun VectorScope.TriangleWithOffsets() {
+private fun TriangleWithOffsets() {
 
     val side1 = 150.0f
     val side2 = 150.0f
@@ -174,7 +173,7 @@
 }
 
 @Composable
-private fun VectorScope.StripePath(vectorWidth: Float, vectorHeight: Float) {
+private fun StripePath(vectorWidth: Float, vectorHeight: Float) {
     val stripeDelegate = PathData {
         stripe(vectorWidth, vectorHeight, 10)
     }
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 28573ff..edbb187 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
@@ -25,9 +25,9 @@
 import androidx.ui.core.AutofillTreeAmbient
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
 import androidx.ui.core.onChildPositioned
 import androidx.ui.core.toComposeRect
+import androidx.ui.foundation.Box
 import androidx.ui.foundation.Text
 import androidx.ui.foundation.TextField
 import androidx.ui.input.ImeAction
@@ -106,8 +106,7 @@
     val autofillTree = AutofillTreeAmbient.current
     autofillTree += autofillNode
 
-    @Suppress("DEPRECATION")
-    PassThroughLayout(onChildPositioned {
+    Box(Modifier.onChildPositioned {
         autofillNode.boundingBox = it.boundingBox().toComposeRect()
     }) {
         children(autofillNode)
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 8fcebd5..b2e2355 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
@@ -37,11 +37,11 @@
 import androidx.ui.unit.dp
 
 /**
- * Simple demo that shows off how DragGestureDetector and ScaleGestureDetector automatically
+ * Simple demo that shows off how [dragGestureFilter] and [scaleGestureFilter] automatically
  * interoperate.
  */
 @Composable
-fun DragAndScaleGestureDetectorDemo() {
+fun DragAndScaleGestureFilterDemo() {
     val size = state { 200.dp }
     val offset = state { Offset.Zero }
     val dragInScale = state { false }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/HorizontalScrollersInVerticalScrollerDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/HorizontalScrollersInVerticalScrollerDemo.kt
new file mode 100644
index 0000000..9ad1b47
--- /dev/null
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/HorizontalScrollersInVerticalScrollerDemo.kt
@@ -0,0 +1,254 @@
+/*
+ * 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.core.demos.gestures
+
+import androidx.compose.Composable
+import androidx.compose.state
+import androidx.ui.core.Constraints
+import androidx.ui.core.ContentDrawScope
+import androidx.ui.core.Direction
+import androidx.ui.core.DrawModifier
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScrollCallback
+import androidx.ui.core.gesture.doubleTapGestureFilter
+import androidx.ui.core.gesture.longPressGestureFilter
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.tapGestureFilter
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.foundation.drawBackground
+import androidx.ui.foundation.drawBorder
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.drawscope.clipRect
+import androidx.ui.layout.Column
+import androidx.ui.layout.Row
+import androidx.ui.layout.preferredSize
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+import kotlin.math.roundToInt
+
+/**
+ * Demonstration for how multiple DragGestureDetectors interact.
+ */
+@Composable
+fun HorizontalScrollersInVerticalScrollersDemo() {
+    Column {
+        Text("Demonstrates scroll orientation locking.")
+        Text(
+            "There is a column of rows, all of which are scrollable. Any one pointer can only " +
+                    "contribute to dragging in one orientation at a time."
+        )
+        Scrollable(Orientation.Vertical) {
+            RepeatingColumn(repetitions = 10) {
+                Box(paddingTop = 8.dp, paddingBottom = 8.dp) {
+                    // Inner composable that scrolls
+                    Scrollable(Orientation.Horizontal) {
+                        RepeatingRow(repetitions = 10) {
+                            // Composable that indicates it is being pressed
+                            Pressable(
+                                width = 96.dp,
+                                height = 96.dp
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+/**
+ * A very simple ScrollView like implementation that allows for vertical scrolling.
+ */
+@Composable
+private fun Scrollable(orientation: Orientation, children: @Composable () -> Unit) {
+    val maxOffset = 0f
+    val offset = state { maxOffset }
+    val minOffset = state { 0f }
+
+    val scrollObserver = object : ScrollCallback {
+        override fun onScroll(scrollDistance: Float): Float {
+            val resultingOffset = offset.value + scrollDistance
+            val toConsume =
+                when {
+                    resultingOffset > maxOffset -> {
+                        maxOffset - offset.value
+                    }
+                    resultingOffset < minOffset.value -> {
+                        minOffset.value - offset.value
+                    }
+                    else -> {
+                        scrollDistance
+                    }
+                }
+            offset.value = offset.value + toConsume
+            return toConsume
+        }
+    }
+
+    val canDrag: (Direction) -> Boolean = { direction ->
+        when {
+            direction == Direction.LEFT && offset.value > minOffset.value -> true
+            direction == Direction.UP && offset.value > minOffset.value -> true
+            direction == Direction.RIGHT && offset.value < maxOffset -> true
+            direction == Direction.DOWN && offset.value < maxOffset -> true
+            else -> false
+        }
+    }
+
+    Layout(
+        children = children,
+        modifier = Modifier.scrollGestureFilter(scrollObserver, orientation, canDrag) +
+                ClipModifier,
+        measureBlock = { measurables, constraints, _ ->
+            val placeable =
+                when (orientation) {
+                    Orientation.Horizontal -> measurables.first().measure(
+                        constraints.copy(
+                            minWidth = 0,
+                            maxWidth = Constraints.Infinity
+                        )
+                    )
+                    Orientation.Vertical -> measurables.first().measure(
+                        constraints.copy(
+                            minHeight = 0,
+                            maxHeight = Constraints.Infinity
+                        )
+                    )
+                }
+
+            minOffset.value =
+                when (orientation) {
+                    Orientation.Horizontal -> constraints.maxWidth.toFloat() - placeable.width
+                    Orientation.Vertical -> constraints.maxHeight.toFloat() - placeable.height
+                }
+
+            val width =
+                when (orientation) {
+                    Orientation.Horizontal -> constraints.maxWidth
+                    Orientation.Vertical -> placeable.width
+                }
+
+            val height =
+                when (orientation) {
+                    Orientation.Horizontal -> placeable.height
+                    Orientation.Vertical -> constraints.maxHeight
+                }
+
+            layout(width, height) {
+                when (orientation) {
+                    Orientation.Horizontal -> placeable.place(offset.value.roundToInt(), 0)
+                    Orientation.Vertical -> placeable.place(0, offset.value.roundToInt())
+                }
+            }
+        })
+}
+
+private val ClipModifier = object : DrawModifier {
+    override fun ContentDrawScope.draw() {
+        clipRect {
+            [email protected]()
+        }
+    }
+}
+
+/**
+ * A very simple Button like implementation that visually indicates when it is being pressed.
+ */
+@Composable
+private fun Pressable(
+    width: Dp,
+    height: Dp
+) {
+
+    val pressedColor = PressedColor
+    val defaultColor = Red
+
+    val color = state { defaultColor }
+    val showPressed = state { false }
+
+    val onPress: (Offset) -> Unit = {
+        showPressed.value = true
+    }
+
+    val onRelease = {
+        showPressed.value = false
+    }
+
+    val onTap: (Offset) -> Unit = {
+        color.value = color.value.next()
+    }
+
+    val onDoubleTap: (Offset) -> Unit = {
+        color.value = color.value.prev()
+    }
+
+    val onLongPress = { _: Offset ->
+        color.value = defaultColor
+        showPressed.value = false
+    }
+
+    val gestureDetectors =
+        Modifier
+            .pressIndicatorGestureFilter(onPress, onRelease, onRelease)
+            .tapGestureFilter(onTap)
+            .doubleTapGestureFilter(onDoubleTap)
+            .longPressGestureFilter(onLongPress)
+
+    val pressOverlay =
+        if (showPressed.value) Modifier.drawBackground(pressedColor) else Modifier
+
+    Box(
+        gestureDetectors
+            .preferredSize(width, height)
+            .drawBorder(1.dp, Color.Black)
+            .drawBackground(color.value)
+            .plus(pressOverlay)
+    )
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingColumn(repetitions: Int, children: @Composable () -> Unit) {
+    Column {
+        for (i in 1..repetitions) {
+            children()
+        }
+    }
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingRow(repetitions: Int, children: @Composable () -> Unit) {
+    Row {
+        for (i in 1..repetitions) {
+            children()
+        }
+    }
+}
\ No newline at end of file
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 5985ff0..9938ab2 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
@@ -24,11 +24,12 @@
 import androidx.ui.core.Modifier
 import androidx.ui.core.clipToBounds
 import androidx.ui.core.gesture.doubleTapGestureFilter
-import androidx.ui.core.gesture.DragObserver
+import androidx.ui.core.gesture.ScrollCallback
 import androidx.ui.core.gesture.longPressGestureFilter
 import androidx.ui.core.gesture.pressIndicatorGestureFilter
 import androidx.ui.core.gesture.tapGestureFilter
-import androidx.ui.core.gesture.dragGestureFilter
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
 import androidx.ui.foundation.Border
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.Text
@@ -52,12 +53,12 @@
         Text("Demonstrates nested scrolling.")
         Text("There are 3 fake vertical scrollers inside another vertical scroller.  Try " +
                 "scrolling with 1 or many fingers.")
-        Draggable {
-            RepeatingList(repetitions = 3) {
+        Scrollable {
+            RepeatingColumn(repetitions = 3) {
                 Box(Modifier.preferredHeight(398.dp), padding = 72.dp) {
                     // Inner composable that scrolls
-                    Draggable {
-                        RepeatingList(repetitions = 5) {
+                    Scrollable {
+                        RepeatingColumn(repetitions = 5) {
                             // Composable that indicates it is being pressed
                             Pressable(
                                 height = 72.dp
@@ -74,13 +75,13 @@
  * A very simple ScrollView like implementation that allows for vertical scrolling.
  */
 @Composable
-private fun Draggable(children: @Composable () -> Unit) {
+private fun Scrollable(children: @Composable () -> Unit) {
     val offset = state { 0f }
     val maxOffset = state { 0f }
 
-    val dragObserver = object : DragObserver {
-        override fun onDrag(dragDistance: Offset): Offset {
-            val resultingOffset = offset.value + dragDistance.y
+    val scrollObserver = object : ScrollCallback {
+        override fun onScroll(scrollDistance: Float): Float {
+            val resultingOffset = offset.value + scrollDistance
             val dyToConsume =
                 when {
                     resultingOffset > 0f -> {
@@ -90,11 +91,11 @@
                         maxOffset.value - offset.value
                     }
                     else -> {
-                        dragDistance.y
+                        scrollDistance
                     }
                 }
-            offset.value = offset.value + dyToConsume
-            return Offset(0f, dyToConsume)
+            offset.value += dyToConsume
+            return dyToConsume
         }
     }
 
@@ -109,7 +110,7 @@
     Layout(
         children = children,
         modifier = Modifier
-            .dragGestureFilter(dragObserver, canDrag)
+            .scrollGestureFilter(scrollObserver, Orientation.Vertical, canDrag)
             .clipToBounds(),
         measureBlock = { measurables, constraints, _ ->
             val placeable =
@@ -151,7 +152,7 @@
     }
 
     val onDoubleTap: (Offset) -> Unit = {
-        color.value = color.value.prev().prev()
+        color.value = color.value.prev()
     }
 
     val onLongPress = { _: Offset ->
@@ -178,7 +179,7 @@
  * times.
  */
 @Composable
-private fun RepeatingList(repetitions: Int, row: @Composable () -> Unit) {
+private fun RepeatingColumn(repetitions: Int, row: @Composable () -> Unit) {
     Column(Modifier.drawBorder(border = Border(2.dp, BorderColor))) {
         for (i in 1..repetitions) {
             row()
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/ScrollGestureFilterDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/ScrollGestureFilterDemo.kt
new file mode 100644
index 0000000..738cd5f
--- /dev/null
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/ScrollGestureFilterDemo.kt
@@ -0,0 +1,110 @@
+/*
+ * 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.core.demos.gestures
+
+import androidx.compose.Composable
+import androidx.compose.emptyContent
+import androidx.compose.state
+import androidx.ui.core.Alignment
+import androidx.ui.core.DensityAmbient
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScrollCallback
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.layout.Column
+import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.offset
+import androidx.ui.layout.preferredSize
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+
+/**
+ * Simple demo that shows off ScrollGestureFilter.
+ */
+@Composable
+fun ScrollGestureFilterDemo() {
+    Column {
+        Text("Demonstrates scroll orientation locking")
+        Text(
+            "The inner box is composed inside of the outer.  If you start dragging the inner box" +
+                    "vertically, it will drag vertically , the same pointer will only ever allow " +
+                    "the box to be dragged vertically.  If drag the inner box horizontally, the " +
+                    "container will start being dragged horizontally and that pointer will only " +
+                    "ever drag horizontally."
+        )
+        ScrollableBox(240.dp, Orientation.Horizontal, Green, Yellow) {
+            ScrollableBox(144.dp, Orientation.Vertical, Red, Blue)
+        }
+    }
+}
+
+@Composable
+fun ScrollableBox(
+    size: Dp,
+    orientation: Orientation,
+    activeColor: Color,
+    idleColor: Color,
+    children: @Composable () -> Unit = emptyContent()
+) {
+
+    val color = state { idleColor }
+    val offsetPx = state { 0f }
+
+    val offsetDp = with(DensityAmbient.current) {
+        offsetPx.value.toDp()
+    }
+
+    val scrollCallback: ScrollCallback = object : ScrollCallback {
+        override fun onStart(downPosition: Offset) {
+            color.value = activeColor
+        }
+
+        override fun onScroll(scrollDistance: Float): Float {
+            offsetPx.value += scrollDistance
+            return scrollDistance
+        }
+
+        override fun onStop(velocity: Float) {
+            color.value = idleColor
+        }
+
+        override fun onCancel() {
+            color.value = idleColor
+        }
+    }
+
+    val (offsetX, offsetY) = when (orientation) {
+        Orientation.Horizontal -> offsetDp to Dp.Hairline
+        Orientation.Vertical -> Dp.Hairline to offsetDp
+    }
+
+    Box(
+            Modifier.offset(offsetX, offsetY)
+                .fillMaxSize()
+                .wrapContentSize(Alignment.Center)
+                .scrollGestureFilter(scrollCallback, orientation)
+                .preferredSize(size),
+            backgroundColor = color.value
+        ) {
+            children()
+        }
+}
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/VerticalScrollerInDrawerLayoutDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/VerticalScrollerInDrawerLayoutDemo.kt
new file mode 100644
index 0000000..66eeb40
--- /dev/null
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/VerticalScrollerInDrawerLayoutDemo.kt
@@ -0,0 +1,307 @@
+/*
+ * 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.core.demos.gestures
+
+import androidx.compose.Composable
+import androidx.compose.state
+import androidx.ui.core.Alignment
+import androidx.ui.core.Constraints
+import androidx.ui.core.ContentDrawScope
+import androidx.ui.core.DensityAmbient
+import androidx.ui.core.Direction
+import androidx.ui.core.DrawModifier
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScrollCallback
+import androidx.ui.core.gesture.doubleTapGestureFilter
+import androidx.ui.core.gesture.longPressGestureFilter
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.tapGestureFilter
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.foundation.drawBackground
+import androidx.ui.foundation.drawBorder
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.drawscope.clipRect
+import androidx.ui.layout.Column
+import androidx.ui.layout.ColumnScope
+import androidx.ui.layout.Row
+import androidx.ui.layout.Stack
+import androidx.ui.layout.fillMaxHeight
+import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.fillMaxWidth
+import androidx.ui.layout.offsetPx
+import androidx.ui.layout.preferredHeight
+import androidx.ui.layout.width
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+import kotlin.math.roundToInt
+
+/**
+ * Demonstration for how multiple DragGestureDetectors interact.
+ */
+@Composable
+fun VerticalScrollerInDrawerDemo() {
+    Column {
+        Text("Demonstrates scroll orientation locking.")
+        Text(
+            "There is a vertically scrolling column and a drawer layout.  A pointer can only " +
+                    "contribute to dragging the column or the drawer, but not both."
+        )
+        DrawerLayout(280.dp) {
+            Scrollable(Orientation.Vertical) {
+                RepeatingColumn(repetitions = 10) {
+                    Pressable(
+                        height = 96.dp
+                    )
+                }
+            }
+        }
+    }
+}
+
+@Composable
+private fun DrawerLayout(drawerWidth: Dp, children: @Composable ColumnScope.() -> Unit) {
+
+    val minOffset =
+        with(DensityAmbient.current) {
+            -drawerWidth.toPx()
+        }
+
+    val currentOffset = state { minOffset }
+    val maxOffset = 0f
+
+    val scrollObserver = object : ScrollCallback {
+        override fun onScroll(scrollDistance: Float): Float {
+            val originalOffset = currentOffset.value
+            currentOffset.value =
+                (currentOffset.value + scrollDistance).coerceIn(minOffset, maxOffset)
+            return currentOffset.value - originalOffset
+        }
+    }
+
+    val canDrag: (Direction) -> Boolean =
+        { direction ->
+            when (direction) {
+                Direction.LEFT -> currentOffset.value > minOffset
+                Direction.RIGHT -> currentOffset.value < 0
+                else -> false
+            }
+        }
+
+    Stack(Modifier.scrollGestureFilter(scrollObserver, Orientation.Horizontal, canDrag)) {
+        Column {
+            children()
+        }
+        Box(
+            Modifier
+                .fillMaxHeight()
+                .width(drawerWidth)
+                .offsetPx(x = currentOffset)
+                .drawBackground(DefaultBackgroundColor)
+        ) {
+            Text(
+                "This is empty drawer content",
+                Modifier
+                    .fillMaxSize()
+                    .wrapContentSize(Alignment.Center)
+            )
+        }
+    }
+}
+
+/**
+ * A very simple ScrollView like implementation that allows for vertical scrolling.
+ */
+@Composable
+private fun Scrollable(orientation: Orientation, children: @Composable () -> Unit) {
+    val maxOffset = 0f
+    val offset = state { maxOffset }
+    val minOffset = state { 0f }
+
+    val scrollObserver = object : ScrollCallback {
+        override fun onScroll(scrollDistance: Float): Float {
+            val resultingOffset = offset.value + scrollDistance
+            val toConsume =
+                when {
+                    resultingOffset > maxOffset -> {
+                        maxOffset - offset.value
+                    }
+                    resultingOffset < minOffset.value -> {
+                        minOffset.value - offset.value
+                    }
+                    else -> {
+                        scrollDistance
+                    }
+                }
+            offset.value = offset.value + toConsume
+            return toConsume
+        }
+    }
+
+    val canDrag: (Direction) -> Boolean = { direction ->
+        when {
+            direction == Direction.LEFT && offset.value > minOffset.value -> true
+            direction == Direction.UP && offset.value > minOffset.value -> true
+            direction == Direction.RIGHT && offset.value < maxOffset -> true
+            direction == Direction.DOWN && offset.value < maxOffset -> true
+            else -> false
+        }
+    }
+
+    Layout(
+        children = children,
+        modifier = Modifier.scrollGestureFilter(scrollObserver, orientation, canDrag) +
+                ClipModifier,
+        measureBlock = { measurables, constraints, _ ->
+            val placeable =
+                when (orientation) {
+                    Orientation.Horizontal -> measurables.first().measure(
+                        constraints.copy(
+                            minWidth = 0,
+                            maxWidth = Constraints.Infinity
+                        )
+                    )
+                    Orientation.Vertical -> measurables.first().measure(
+                        constraints.copy(
+                            minHeight = 0,
+                            maxHeight = Constraints.Infinity
+                        )
+                    )
+                }
+
+            minOffset.value =
+                when (orientation) {
+                    Orientation.Horizontal -> constraints.maxWidth.toFloat() - placeable.width
+                    Orientation.Vertical -> constraints.maxHeight.toFloat() - placeable.height
+                }
+
+            val width =
+                when (orientation) {
+                    Orientation.Horizontal -> constraints.maxWidth
+                    Orientation.Vertical -> placeable.width
+                }
+
+            val height =
+                when (orientation) {
+                    Orientation.Horizontal -> placeable.height
+                    Orientation.Vertical -> constraints.maxHeight
+                }
+
+            layout(width, height) {
+                when (orientation) {
+                    Orientation.Horizontal -> placeable.place(offset.value.roundToInt(), 0)
+                    Orientation.Vertical -> placeable.place(0, offset.value.roundToInt())
+                }
+            }
+        })
+}
+
+private val ClipModifier = object : DrawModifier {
+    override fun ContentDrawScope.draw() {
+        clipRect {
+            [email protected]()
+        }
+    }
+}
+
+/**
+ * A very simple Button like implementation that visually indicates when it is being pressed.
+ */
+@Composable
+private fun Pressable(
+    height: Dp
+) {
+
+    val pressedColor = PressedColor
+    val defaultColor = Red
+
+    val color = state { defaultColor }
+    val showPressed = state { false }
+
+    val onPress: (Offset) -> Unit = {
+        showPressed.value = true
+    }
+
+    val onRelease = {
+        showPressed.value = false
+    }
+
+    val onTap: (Offset) -> Unit = {
+        color.value = color.value.next()
+    }
+
+    val onDoubleTap: (Offset) -> Unit = {
+        color.value = color.value.prev()
+    }
+
+    val onLongPress = { _: Offset ->
+        color.value = defaultColor
+        showPressed.value = false
+    }
+
+    val gestureDetectors =
+        Modifier
+            .pressIndicatorGestureFilter(onPress, onRelease, onRelease)
+            .tapGestureFilter(onTap)
+            .doubleTapGestureFilter(onDoubleTap)
+            .longPressGestureFilter(onLongPress)
+
+    val pressOverlay =
+        if (showPressed.value) Modifier.drawBackground(pressedColor) else Modifier
+
+    Box(
+        Modifier
+            .fillMaxWidth()
+            .preferredHeight(height)
+            .drawBorder(1.dp, Color.Black)
+            .drawBackground(color.value)
+            .plus(pressOverlay) + gestureDetectors
+    )
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingColumn(repetitions: Int, children: @Composable () -> Unit) {
+    Column {
+        for (i in 1..repetitions) {
+            children()
+        }
+    }
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingRow(repetitions: Int, children: @Composable () -> Unit) {
+    Row {
+        for (i in 1..repetitions) {
+            children()
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt
index 2387c2c..562e520 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt
@@ -38,6 +38,7 @@
 import androidx.ui.layout.Column
 import androidx.ui.material.Button
 import androidx.ui.viewinterop.AndroidView
+import androidx.ui.viewinterop.emitView
 
 @Composable
 fun ViewInComposeDemo() {
@@ -46,10 +47,14 @@
         // UI hierarchies. Note that these APIs are subject to change.
 
         // Include Android View.
-        TextView(text = "This is a text in a TextView")
+        emitView(::TextView) {
+            it.text = "This is a text in a TextView"
+        }
         val ref = Ref<View>()
-        FrameLayout(ref = ref) {
-            android.widget.TextView(text = "This is a very long very long text")
+        emitView(::FrameLayout, { it.setRef(ref) }) {
+            emitView(::TextView) {
+                it.text = "This is a very long very long text"
+            }
         }
         Text("This is a second text")
         ref.value!!.layoutParams = ViewGroup.LayoutParams(100, WRAP_CONTENT)
@@ -67,12 +72,12 @@
 
         // Compose custom Android View and do remeasurements and invalidates.
         val squareRef = Ref<ColoredSquareView>()
-        FrameLayout {
-            ColoredSquareView(
-                size = 200,
-                color = Color.Cyan,
-                ref = squareRef
-            )
+        emitView(::FrameLayout, {}) {
+            emitView(::ColoredSquareView) {
+                it.size = 200
+                it.color = Color.Cyan
+                it.setRef(squareRef)
+            }
         }
         Button(onClick = { squareRef.value!!.size += 50 }) {
             Text("Increase size of Android view")
diff --git a/ui/ui-core/samples/src/main/java/androidx/ui/core/samples/EmitViewSamples.kt b/ui/ui-core/samples/src/main/java/androidx/ui/core/samples/EmitViewSamples.kt
new file mode 100644
index 0000000..0c3cb3b
--- /dev/null
+++ b/ui/ui-core/samples/src/main/java/androidx/ui/core/samples/EmitViewSamples.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.samples
+
+import android.view.View
+import androidx.annotation.Sampled
+import androidx.compose.Composable
+import android.widget.Button
+import android.widget.LinearLayout
+import androidx.ui.viewinterop.emitView
+
+@Sampled
+@Composable
+fun EmitViewButtonSample() {
+    @Composable
+    fun Button(
+        text: String,
+        onClick: (() -> Unit)? = null
+    ) {
+        emitView<Button>(::Button) {
+            it.text = text
+            it.setOnClickListener(onClick?.let { View.OnClickListener { it() } })
+        }
+    }
+}
+
+@Sampled
+@Composable
+fun EmitViewLinearLayoutSample() {
+    @Composable
+    fun LinearLayout(
+        orientation: Int = android.widget.LinearLayout.VERTICAL,
+        children: @Composable () -> Unit
+    ) {
+        emitView<LinearLayout>(::LinearLayout, { it.orientation = orientation }) {
+            children()
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt
index a86da8a..ed0d0f6 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt
@@ -25,7 +25,6 @@
 import androidx.compose.FrameManager
 import androidx.compose.Recomposer
 import androidx.compose.emptyContent
-import androidx.compose.escapeCompose
 import androidx.compose.getValue
 import androidx.compose.mutableStateOf
 import androidx.compose.remember
@@ -348,13 +347,12 @@
 
 @Composable
 fun AndroidWithCompose(context: Context, androidPadding: Int, children: @Composable () -> Unit) {
-    val anotherLayout =
-        escapeCompose { FrameLayout(context) }.also { view ->
-            view.setContent(Recomposer.current()) {
-                children()
-            }
-            view.setPadding(androidPadding, androidPadding, androidPadding, androidPadding)
+    val anotherLayout = FrameLayout(context).also { view ->
+        view.setContent(Recomposer.current()) {
+            children()
         }
+        view.setPadding(androidPadding, androidPadding, androidPadding, androidPadding)
+    }
     AndroidView(anotherLayout)
 }
 
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt
index 58b1eb9..b2ebce3 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt
@@ -22,12 +22,14 @@
 import android.widget.TextView
 import androidx.compose.clearRoots
 import androidx.compose.Composable
+import androidx.compose.emit
 import androidx.compose.onCommit
 import androidx.compose.simulateHotReload
 import androidx.test.filters.MediumTest
 import androidx.ui.core.semantics.semantics
 import androidx.ui.foundation.Box
 import androidx.ui.framework.test.TestActivity
+import androidx.ui.node.UiApplier
 import androidx.ui.semantics.accessibilityLabel
 import androidx.ui.test.android.AndroidComposeTestRule
 import androidx.ui.test.assertLabelEquals
@@ -62,11 +64,23 @@
         var value = "First value"
 
         @Composable fun text(text: String, id: Int = -1) {
-            TextView(id = id, text = text)
+            val context = ContextAmbient.current
+            emit<TextView, UiApplier>(
+                ctor = { TextView(context) },
+                update = {
+                    set(id) { this.id = it }
+                    set(text) { this.text = it }
+                }
+            )
         }
 
         @Composable fun column(children: @Composable () -> Unit) {
-            LinearLayout { children() }
+            val context = ContextAmbient.current
+            emit<LinearLayout, UiApplier>(
+                ctor = { LinearLayout(context) },
+                update = {},
+                children = children
+            )
         }
 
         val composeLatch = CountDownLatch(1)
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt
index b9852fa..97c6aba 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt
@@ -26,6 +26,7 @@
 import androidx.ui.framework.test.TestActivity
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.toArgb
+import androidx.ui.text.InternalTextApi
 import androidx.ui.text.style.TextDirection
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.mock
@@ -38,6 +39,7 @@
 
 @SmallTest
 @RunWith(JUnit4::class)
+@OptIn(InternalTextApi::class)
 class SelectionHandlesTest {
     @Suppress("DEPRECATION")
     @get:Rule
@@ -87,9 +89,15 @@
     fun StartSelectionHandle_left_pointing() {
         rule.runOnUiThreadIR {
             activity.setContent {
-                SelectionHandle(Modifier,
+                SelectionHandle(
+                    modifier = Modifier,
                     isStartHandle = true,
-                    selection = selectionLtrHandleDirection)
+                    directions = Pair(
+                        selectionLtrHandleDirection.start.direction,
+                        selectionLtrHandleDirection.end.direction
+                    ),
+                    handlesCrossed = selectionLtrHandleDirection.handlesCrossed
+                )
             }
         }
 
@@ -105,9 +113,15 @@
     fun StartSelectionHandle_right_pointing() {
         rule.runOnUiThreadIR {
             activity.setContent {
-                SelectionHandle(Modifier,
+                SelectionHandle(
+                    modifier = Modifier,
                     isStartHandle = true,
-                    selection = selectionRtlHandleDirection)
+                    directions = Pair(
+                        selectionRtlHandleDirection.start.direction,
+                        selectionRtlHandleDirection.end.direction
+                    ),
+                    handlesCrossed = selectionRtlHandleDirection.handlesCrossed
+                )
             }
         }
 
@@ -123,9 +137,15 @@
     fun EndSelectionHandle_right_pointing() {
         rule.runOnUiThreadIR {
             activity.setContent {
-                SelectionHandle(Modifier,
+                SelectionHandle(
+                    modifier = Modifier,
                     isStartHandle = false,
-                    selection = selectionLtrHandleDirection)
+                    directions = Pair(
+                        selectionLtrHandleDirection.start.direction,
+                        selectionLtrHandleDirection.end.direction
+                    ),
+                    handlesCrossed = selectionLtrHandleDirection.handlesCrossed
+                )
             }
         }
 
@@ -141,9 +161,15 @@
     fun EndSelectionHandle_left_pointing() {
         rule.runOnUiThreadIR {
             activity.setContent {
-                SelectionHandle(Modifier,
+                SelectionHandle(
+                    modifier = Modifier,
                     isStartHandle = false,
-                    selection = selectionRtlHandleDirection)
+                    directions = Pair(
+                        selectionRtlHandleDirection.start.direction,
+                        selectionRtlHandleDirection.end.direction
+                    ),
+                    handlesCrossed = selectionRtlHandleDirection.handlesCrossed
+                )
             }
         }
 
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index f66e670..8d7708a 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -56,7 +56,6 @@
 import androidx.ui.core.Modifier
 import androidx.ui.core.Owner
 import androidx.ui.core.ParentDataModifier
-import androidx.ui.core.PassThroughLayout
 import androidx.ui.core.Ref
 import androidx.ui.core.VerticalAlignmentLine
 import androidx.ui.core.constrainHeight
@@ -87,6 +86,7 @@
 import androidx.ui.unit.dp
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertSame
 import org.junit.Assert.assertTrue
 import org.junit.Assert.fail
@@ -2325,27 +2325,6 @@
         assertFalse(outerLatch.await(200, TimeUnit.MILLISECONDS))
     }
 
-    @Test
-    fun passThroughLayout_passesThroughParentData() {
-        val latch = CountDownLatch(1)
-        activityTestRule.runOnUiThread {
-            activity.setContent {
-                Layout({
-                    PassThroughLayout {
-                        FixedSize(50, Modifier.layoutId("1"))
-                    }
-                }) { measurables, constraints, _ ->
-                    assertEquals("1", measurables[0].id)
-                    val placeable = measurables[0].measure(constraints)
-                    assertEquals(50, placeable.width)
-                    latch.countDown()
-                    layout(0, 0) {}
-                }
-            }
-        }
-        assertTrue(latch.await(1, TimeUnit.SECONDS))
-    }
-
     // When a child with a layer is removed with its children, it shouldn't crash.
     @Test
     fun detachChildWithLayer() {
@@ -2461,6 +2440,106 @@
         }
     }
 
+    // Delegates don't change when the modifier types remain the same
+    @Test
+    fun instancesKeepDelegates() {
+        var color by mutableStateOf(Color.Red)
+        var m: Measurable? = null
+        val layoutCaptureModifier = object : LayoutModifier {
+            override fun MeasureScope.measure(
+                measurable: Measurable,
+                constraints: Constraints,
+                layoutDirection: LayoutDirection
+            ): MeasureScope.MeasureResult {
+                m = measurable
+                val p = measurable.measure(constraints, layoutDirection)
+                drawLatch.countDown()
+                return layout(p.width, p.height) {
+                    p.place(0, 0)
+                }
+            }
+        }
+        activityTestRule.runOnUiThread {
+            activity.setContent {
+                FixedSize(30, layoutCaptureModifier.background(color)) {}
+            }
+        }
+        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+        var firstMeasurable = m
+        drawLatch = CountDownLatch(1)
+
+        activityTestRule.runOnUiThread {
+            m = null
+            color = Color.Blue
+        }
+
+        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+        assertNotNull(m)
+        assertSame(firstMeasurable, m)
+    }
+
+    // LayoutNodeWrappers remain even when there are multiple for a modifier
+    @Test
+    fun replaceMultiImplementationModifier() {
+        var color by mutableStateOf(Color.Red)
+        var m: Measurable? = null
+
+        var layerLatch = CountDownLatch(1)
+
+        class SpecialModifier(
+            val drawLatch: CountDownLatch,
+            val layerLatch: CountDownLatch
+        ) : DrawModifier, DrawLayerModifier {
+            override fun ContentDrawScope.draw() {
+                drawContent()
+                drawLatch.countDown()
+            }
+
+            override val translationX: Float
+                get() {
+                    layerLatch.countDown()
+                    return super.translationX
+                }
+        }
+
+        val layoutCaptureModifier = object : LayoutModifier {
+            override fun MeasureScope.measure(
+                measurable: Measurable,
+                constraints: Constraints,
+                layoutDirection: LayoutDirection
+            ): MeasureScope.MeasureResult {
+                m = measurable
+                val p = measurable.measure(constraints, layoutDirection)
+                return layout(p.width, p.height) {
+                    p.place(0, 0)
+                }
+            }
+        }
+        activityTestRule.runOnUiThread {
+            activity.setContent {
+                FixedSize(30, layoutCaptureModifier +
+                        SpecialModifier(drawLatch, layerLatch).background(color)) {}
+            }
+        }
+        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+        assertTrue(layerLatch.await(1, TimeUnit.SECONDS))
+        var firstMeasurable = m
+        drawLatch = CountDownLatch(1)
+        layerLatch = CountDownLatch(1)
+
+        activityTestRule.runOnUiThread {
+            m = null
+            color = Color.Blue
+        }
+
+        // The latches are triggered in the new instance
+        assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+        assertTrue(layerLatch.await(1, TimeUnit.SECONDS))
+        // The new instance's measurable is the same.
+        assertNotNull(m)
+        assertSame(firstMeasurable, m)
+    }
+
     private fun composeSquares(model: SquareModel) {
         activityTestRule.runOnUiThreadIR {
             activity.setContent {
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt
index 8f37987..2862ab1 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt
@@ -56,6 +56,7 @@
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.runOnUiThread
 import androidx.ui.unit.IntOffset
+import androidx.ui.viewinterop.emitView
 import junit.framework.TestCase.assertNotNull
 import org.hamcrest.CoreMatchers.`is`
 import org.hamcrest.CoreMatchers.instanceOf
@@ -84,7 +85,11 @@
                 Layout(
                     modifier = Modifier.testTag("content"),
                     children = @Composable {
-                        ColoredSquareView(size = squareSize.value, ref = squareRef)
+
+                        emitView(::ColoredSquareView) {
+                            it.size = squareSize.value
+                            it.ref = squareRef
+                        }
                     }
                 ) { measurables, constraints, _ ->
                     assertEquals(1, measurables.size)
@@ -140,7 +145,10 @@
         composeTestRule.setContent {
             Align {
                 Container(Modifier.testTag("content").drawLayer()) {
-                    ColoredSquareView(color = colorModel.value, ref = squareRef)
+                    emitView(::ColoredSquareView) {
+                        it.color = colorModel.value
+                        it.ref = squareRef
+                    }
                 }
             }
         }
@@ -328,11 +336,11 @@
 
         composeTestRule.setContent {
             Container(LayoutConstraints(constraintsHolder.value)) {
-                MeasureSpecSaverView(
-                    ref = viewRef,
-                    widthMeasureSpecRef = widthMeasureSpecRef,
-                    heightMeasureSpecRef = heightMeasureSpecRef
-                )
+                emitView(::MeasureSpecSaverView) {
+                    it.ref = viewRef
+                    it.widthMeasureSpecRef = widthMeasureSpecRef
+                    it.heightMeasureSpecRef = heightMeasureSpecRef
+                }
             }
         }
 
@@ -353,7 +361,7 @@
         val constraintsHolder = mutableStateOf(Constraints())
         composeTestRule.setContent {
             Container(LayoutConstraints(constraintsHolder.value)) {
-                MeasureSpecSaverView(ref = viewRef)
+                emitView(::MeasureSpecSaverView) { it.ref = viewRef }
             }
         }
         runOnUiThread {
@@ -445,4 +453,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt
index 2324088..658288a 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt
@@ -63,16 +63,16 @@
         assertEquals(10.0f, moveTo.y)
 
         val relativeLineTo1 = path[1].assertType<PathNode.RelativeLineTo>()
-        assertEquals(10.0f, relativeLineTo1.x)
-        assertEquals(0.0f, relativeLineTo1.y)
+        assertEquals(10.0f, relativeLineTo1.dx)
+        assertEquals(0.0f, relativeLineTo1.dy)
 
         val relativeLineTo2 = path[2].assertType<PathNode.RelativeLineTo>()
-        assertEquals(0.0f, relativeLineTo2.x)
-        assertEquals(10.0f, relativeLineTo2.y)
+        assertEquals(0.0f, relativeLineTo2.dx)
+        assertEquals(10.0f, relativeLineTo2.dy)
 
         val relativeLineTo3 = path[3].assertType<PathNode.RelativeLineTo>()
-        assertEquals(-10.0f, relativeLineTo3.x)
-        assertEquals(0.0f, relativeLineTo3.y)
+        assertEquals(-10.0f, relativeLineTo3.dx)
+        assertEquals(0.0f, relativeLineTo3.dy)
 
         path[4].assertType<PathNode.Close>()
     }
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt
index 288ace5..427e094 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.viewinterop
 
+import android.os.Build
 import android.util.DisplayMetrics
 import android.util.TypedValue
 import android.view.ViewGroup
@@ -30,6 +31,7 @@
 import androidx.test.espresso.assertion.ViewAssertions.matches
 import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
 import androidx.test.espresso.matcher.ViewMatchers.withClassName
+import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.ui.core.Modifier
 import androidx.ui.core.test.R
@@ -171,6 +173,7 @@
     }
 
     @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun androidViewWithView_drawModifierIsApplied() {
         val size = 300
         lateinit var frameLayout: FrameLayout
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/compose/ComposerCompat.kt b/ui/ui-core/src/androidMain/kotlin/androidx/compose/ComposerCompat.kt
deleted file mode 100644
index 93ff04a..0000000
--- a/ui/ui-core/src/androidMain/kotlin/androidx/compose/ComposerCompat.kt
+++ /dev/null
@@ -1,33 +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.compose
-
-import androidx.ui.node.UiComposer
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
-    "This property should not be called directly. It is only used by the compiler.",
-    replaceWith = ReplaceWith("currentComposer")
-)
-val composer: UiComposer
-    get() = error(
-        "This property should not be called directly. It is only used by the compiler."
-    )
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
index adbcceb..f6bb774 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
@@ -31,14 +31,11 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewStructure
-import android.view.accessibility.AccessibilityEvent
-import android.view.accessibility.AccessibilityManager
 import android.view.autofill.AutofillValue
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
 import androidx.core.os.HandlerCompat
 import androidx.core.view.ViewCompat
-import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.ViewModelStoreOwner
 import androidx.lifecycle.ViewTreeLifecycleOwner
@@ -63,8 +60,6 @@
 import androidx.ui.core.semantics.SemanticsNode
 import androidx.ui.core.semantics.SemanticsModifierCore
 import androidx.ui.core.semantics.SemanticsOwner
-import androidx.ui.core.semantics.getAllSemanticsNodesToMap
-import androidx.ui.core.semantics.getOrNull
 import androidx.ui.core.text.AndroidFontResourceLoader
 import androidx.ui.core.texttoolbar.AndroidTextToolbar
 import androidx.ui.core.texttoolbar.TextToolbar
@@ -80,11 +75,9 @@
 import androidx.ui.input.TextInputServiceAndroid
 import androidx.ui.input.textInputServiceFactory
 import androidx.ui.savedinstancestate.UiSavedStateRegistry
-import androidx.ui.semantics.SemanticsProperties
 import androidx.ui.text.font.Font
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntOffset
-import androidx.ui.unit.max
 import androidx.ui.util.fastForEach
 import androidx.ui.util.trace
 import java.lang.reflect.Method
@@ -116,14 +109,12 @@
 ) : ViewGroup(context), AndroidOwner {
 
     override val view: View = this
-    private val accessibilityDelegate = AndroidComposeViewAccessibilityDelegateCompat(this)
 
     override var density = Density(context)
         private set
 
     private val semanticsModifier = SemanticsModifierCore(
         id = SemanticsNode.generateNewId(),
-        applyToChildLayoutNode = false,
         mergeAllDescendants = false,
         properties = null
     )
@@ -137,23 +128,8 @@
         it.modifier = Modifier.drawLayer() + semanticsModifier + focusModifier + keyInputModifier
     }
 
-    private inner class SemanticsNodeCopy(
-        semanticsNode: SemanticsNode
-    ) {
-        val config = semanticsNode.config
-        val children: MutableSet<Int> = mutableSetOf()
-
-        init {
-            semanticsNode.children.fastForEach { child ->
-                children.add(child.id)
-            }
-        }
-    }
-
     override val semanticsOwner: SemanticsOwner = SemanticsOwner(root)
-    private var semanticsNodes: MutableMap<Int, SemanticsNodeCopy> = mutableMapOf()
-    private var semanticsRoot = SemanticsNodeCopy(semanticsOwner.rootSemanticsNode)
-    private var checkingForSemanticsChanges = false
+    private val accessibilityDelegate = AndroidComposeViewAccessibilityDelegateCompat(this)
 
     // Used by components that want to provide autofill semantic information.
     // TODO: Replace with SemanticsTree: Temporary hack until we have a semantics tree implemented.
@@ -199,16 +175,6 @@
         }
     }
 
-    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 sendKeyEvent(keyEvent: KeyEvent): Boolean {
         return keyInputModifier.processKeyInput(keyEvent)
     }
@@ -312,15 +278,20 @@
 
     private val measureAndLayoutDelegate = MeasureAndLayoutDelegate(root)
 
+    private var measureAndLayoutScheduled = false
+
     private val measureAndLayoutHandler: Handler =
         HandlerCompat.createAsync(Looper.getMainLooper()) {
+            measureAndLayoutScheduled = false
             measureAndLayout()
             true
         }
 
     private fun scheduleMeasureAndLayout() {
-        measureAndLayoutHandler.removeMessages(0)
-        measureAndLayoutHandler.sendEmptyMessage(0)
+        if (!isLayoutRequested && !measureAndLayoutScheduled) {
+            measureAndLayoutScheduled = true
+            measureAndLayoutHandler.sendEmptyMessage(0)
+        }
     }
 
     override val measureIteration: Long get() = measureAndLayoutDelegate.measureIteration
@@ -415,15 +386,7 @@
     }
 
     override fun onSemanticsChange() {
-        if ((context.getSystemService(Context.ACCESSIBILITY_SERVICE)
-                    as AccessibilityManager).isEnabled && !checkingForSemanticsChanges
-        ) {
-            checkingForSemanticsChanges = true
-            Handler(Looper.getMainLooper()).post {
-                checkForSemanticsChanges()
-                checkingForSemanticsChanges = false
-            }
-        }
+        accessibilityDelegate.onSemanticsChange()
     }
 
     private fun updateLayerProperties(layer: OwnedLayer) {
@@ -432,94 +395,6 @@
         }
     }
 
-    private fun checkForSemanticsChanges() {
-        val newSemanticsNodes = semanticsOwner.getAllSemanticsNodesToMap()
-
-        // Structural change
-        sendSemanticsStructureChangeEvents(semanticsOwner.rootSemanticsNode, semanticsRoot)
-
-        // Property change
-        for (id in newSemanticsNodes.keys) {
-            if (semanticsNodes.contains(id)) {
-                // We do doing this search because the new configuration is set as a whole, so we
-                // can't indicate which property is changed when setting the new configuration.
-                var newNode = newSemanticsNodes[id]
-                var oldNode = semanticsNodes[id]
-                for (entry in newNode!!.config) {
-                    if (entry.value == oldNode!!.config.getOrNull(entry.key)) {
-                        continue
-                    }
-                    when (entry.key) {
-                        // we are in aosp, so can't use the state description yet.
-                        SemanticsProperties.AccessibilityValue,
-                        SemanticsProperties.AccessibilityLabel ->
-                            accessibilityDelegate.sendEventForVirtualView(
-                                semanticsNodeIdToAccessibilityVirtualNodeId(id),
-                                AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
-                                AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
-                                entry.value as CharSequence
-                            )
-                        else -> {
-                            // TODO(b/151840490) send the correct events when property changes
-                        }
-                    }
-                }
-            }
-        }
-
-        // Update the cache
-        semanticsNodes.clear()
-        for (entry in newSemanticsNodes.entries) {
-            semanticsNodes[entry.key] = SemanticsNodeCopy(entry.value)
-        }
-        semanticsRoot = SemanticsNodeCopy(semanticsOwner.rootSemanticsNode)
-    }
-
-    private fun sendSemanticsStructureChangeEvents(
-        newNode: SemanticsNode,
-        oldNode: SemanticsNodeCopy
-    ) {
-        var newChildren: MutableSet<Int> = mutableSetOf()
-
-        // If any child is added, clear the subtree rooted at this node and return.
-        newNode.children.fastForEach { child ->
-            if (!oldNode.children.contains(child.id)) {
-                accessibilityDelegate.sendEventForVirtualView(
-                    semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
-                    AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
-                    AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
-                    null
-                )
-                return
-            }
-            newChildren.add(child.id)
-        }
-
-        // If any child is deleted, clear the subtree rooted at this node and return.
-        for (child in oldNode.children) {
-            if (!newChildren.contains(child)) {
-                accessibilityDelegate.sendEventForVirtualView(
-                    semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
-                    AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
-                    AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
-                    null
-                )
-                return
-            }
-        }
-
-        newNode.children.fastForEach { child ->
-            sendSemanticsStructureChangeEvents(child, semanticsNodes[child.id]!!)
-        }
-    }
-
-    private fun semanticsNodeIdToAccessibilityVirtualNodeId(id: Int): Int {
-        if (id == semanticsOwner.rootSemanticsNode.id) {
-            return AccessibilityNodeProviderCompat.HOST_VIEW_ID
-        }
-        return id
-    }
-
     override fun dispatchDraw(canvas: android.graphics.Canvas) {
         measureAndLayout()
         // we don't have to observe here because the root has a layer modifier
@@ -586,6 +461,9 @@
         super.onDetachedFromWindow()
         modelObserver.enableModelUpdatesObserving(false)
         ifDebug { if (autofillSupported()) _autofill?.unregisterCallback() }
+        if (measureAndLayoutScheduled) {
+            measureAndLayoutHandler.removeMessages(0)
+        }
         root.detach()
     }
 
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
index a43eb7b..66052a2 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
@@ -18,6 +18,8 @@
 
 import android.content.Context
 import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
 import android.text.TextUtils
 import android.view.MotionEvent
 import android.view.View
@@ -33,6 +35,7 @@
 import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
 import androidx.ui.core.semantics.SemanticsNode
 import androidx.ui.core.semantics.findChildById
+import androidx.ui.core.semantics.getAllSemanticsNodesToMap
 import androidx.ui.core.semantics.getOrNull
 import androidx.ui.semantics.CustomAccessibilityAction
 import androidx.ui.semantics.SemanticsActions
@@ -52,45 +55,45 @@
          */
         const val ParcelSafeTextLength = 100000
         private val AccessibilityActionsResourceIds = intArrayOf(
-            androidx.ui.core.R.id.accessibility_custom_action_0,
-            androidx.ui.core.R.id.accessibility_custom_action_1,
-            androidx.ui.core.R.id.accessibility_custom_action_2,
-            androidx.ui.core.R.id.accessibility_custom_action_3,
-            androidx.ui.core.R.id.accessibility_custom_action_4,
-            androidx.ui.core.R.id.accessibility_custom_action_5,
-            androidx.ui.core.R.id.accessibility_custom_action_6,
-            androidx.ui.core.R.id.accessibility_custom_action_7,
-            androidx.ui.core.R.id.accessibility_custom_action_8,
-            androidx.ui.core.R.id.accessibility_custom_action_9,
-            androidx.ui.core.R.id.accessibility_custom_action_10,
-            androidx.ui.core.R.id.accessibility_custom_action_11,
-            androidx.ui.core.R.id.accessibility_custom_action_12,
-            androidx.ui.core.R.id.accessibility_custom_action_13,
-            androidx.ui.core.R.id.accessibility_custom_action_14,
-            androidx.ui.core.R.id.accessibility_custom_action_15,
-            androidx.ui.core.R.id.accessibility_custom_action_16,
-            androidx.ui.core.R.id.accessibility_custom_action_17,
-            androidx.ui.core.R.id.accessibility_custom_action_18,
-            androidx.ui.core.R.id.accessibility_custom_action_19,
-            androidx.ui.core.R.id.accessibility_custom_action_20,
-            androidx.ui.core.R.id.accessibility_custom_action_21,
-            androidx.ui.core.R.id.accessibility_custom_action_22,
-            androidx.ui.core.R.id.accessibility_custom_action_23,
-            androidx.ui.core.R.id.accessibility_custom_action_24,
-            androidx.ui.core.R.id.accessibility_custom_action_25,
-            androidx.ui.core.R.id.accessibility_custom_action_26,
-            androidx.ui.core.R.id.accessibility_custom_action_27,
-            androidx.ui.core.R.id.accessibility_custom_action_28,
-            androidx.ui.core.R.id.accessibility_custom_action_29,
-            androidx.ui.core.R.id.accessibility_custom_action_30,
-            androidx.ui.core.R.id.accessibility_custom_action_31
+            R.id.accessibility_custom_action_0,
+            R.id.accessibility_custom_action_1,
+            R.id.accessibility_custom_action_2,
+            R.id.accessibility_custom_action_3,
+            R.id.accessibility_custom_action_4,
+            R.id.accessibility_custom_action_5,
+            R.id.accessibility_custom_action_6,
+            R.id.accessibility_custom_action_7,
+            R.id.accessibility_custom_action_8,
+            R.id.accessibility_custom_action_9,
+            R.id.accessibility_custom_action_10,
+            R.id.accessibility_custom_action_11,
+            R.id.accessibility_custom_action_12,
+            R.id.accessibility_custom_action_13,
+            R.id.accessibility_custom_action_14,
+            R.id.accessibility_custom_action_15,
+            R.id.accessibility_custom_action_16,
+            R.id.accessibility_custom_action_17,
+            R.id.accessibility_custom_action_18,
+            R.id.accessibility_custom_action_19,
+            R.id.accessibility_custom_action_20,
+            R.id.accessibility_custom_action_21,
+            R.id.accessibility_custom_action_22,
+            R.id.accessibility_custom_action_23,
+            R.id.accessibility_custom_action_24,
+            R.id.accessibility_custom_action_25,
+            R.id.accessibility_custom_action_26,
+            R.id.accessibility_custom_action_27,
+            R.id.accessibility_custom_action_28,
+            R.id.accessibility_custom_action_29,
+            R.id.accessibility_custom_action_30,
+            R.id.accessibility_custom_action_31
         )
     }
     /** Virtual view id for the currently hovered logical item. */
     private var hoveredVirtualViewId = InvalidId
     private val accessibilityManager: AccessibilityManager =
-        view.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE) as
-                AccessibilityManager
+        view.context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
+    private val handler = Handler(Looper.getMainLooper())
     private var nodeProvider: AccessibilityNodeProviderCompat = MyNodeProvider()
     private var focusedVirtualViewId = InvalidId
     // For actionIdToId and labelToActionId, the keys are the virtualViewIds. The value of
@@ -99,6 +102,23 @@
     private var actionIdToLabel = SparseArrayCompat<SparseArrayCompat<CharSequence>>()
     private var labelToActionId = SparseArrayCompat<Map<CharSequence, Int>>()
 
+    private class SemanticsNodeCopy(
+        semanticsNode: SemanticsNode
+    ) {
+        val config = semanticsNode.config
+        val children: MutableSet<Int> = mutableSetOf()
+
+        init {
+            semanticsNode.children.fastForEach { child ->
+                children.add(child.id)
+            }
+        }
+    }
+
+    private var semanticsNodes: MutableMap<Int, SemanticsNodeCopy> = mutableMapOf()
+    private var semanticsRoot = SemanticsNodeCopy(view.semanticsOwner.rootSemanticsNode)
+    private var checkingForSemanticsChanges = false
+
     fun createNodeInfo(virtualViewId: Int):
             AccessibilityNodeInfoCompat {
         val info: AccessibilityNodeInfoCompat = AccessibilityNodeInfoCompat.obtain()
@@ -131,7 +151,7 @@
 
         // TODO(b/151240295): Should we have widgets class name?
         info.className = ClassName
-        info.setPackageName(view.getContext().getPackageName())
+        info.packageName = view.context.packageName
         try {
             info.setBoundsInScreen(
                 android.graphics.Rect(
@@ -153,13 +173,13 @@
 
         // Manage internal accessibility focus state.
         if (focusedVirtualViewId == virtualViewId) {
-            info.setAccessibilityFocused(true)
+            info.isAccessibilityFocused = true
             info.addAction(
                 AccessibilityNodeInfoCompat.AccessibilityActionCompat
                     .ACTION_CLEAR_ACCESSIBILITY_FOCUS
             )
         } else {
-            info.setAccessibilityFocused(false)
+            info.isAccessibilityFocused = false
             info.addAction(
                 AccessibilityNodeInfoCompat.AccessibilityActionCompat
                     .ACTION_ACCESSIBILITY_FOCUS
@@ -212,7 +232,7 @@
             )
         }
 
-        var rangeInfo =
+        val rangeInfo =
             semanticsNode.config.getOrNull(SemanticsProperties.AccessibilityRangeInfo)
         if (rangeInfo != null) {
             info.rangeInfo = AccessibilityNodeInfoCompat.RangeInfoCompat.obtain(
@@ -222,26 +242,26 @@
         }
 
         if (semanticsNode.config.contains(CustomActions)) {
-            var customActions = semanticsNode.config[CustomActions]
+            val customActions = semanticsNode.config[CustomActions]
             if (customActions.size >= AccessibilityActionsResourceIds.size) {
                 throw IllegalStateException(
                     "Can't have more than " +
                             "${AccessibilityActionsResourceIds.size} custom actions for one widget"
                 )
             }
-            var currentActionIdToLabel = SparseArrayCompat<CharSequence>()
-            var currentLabelToActionId = mutableMapOf<CharSequence, Int>()
+            val currentActionIdToLabel = SparseArrayCompat<CharSequence>()
+            val currentLabelToActionId = mutableMapOf<CharSequence, Int>()
             // If this virtual node had custom action id assignment before, we try to keep the id
             // unchanged for the same action (identified by action label). This way, we can
             // minimize the influence of custom action change between custom actions are
             // presented to the user and actually performed.
             if (labelToActionId.containsKey(virtualViewId)) {
-                var oldLabelToActionId = labelToActionId[virtualViewId]
-                var availableIds = AccessibilityActionsResourceIds.toMutableList()
-                var unassignedActions = mutableListOf<CustomAccessibilityAction>()
+                val oldLabelToActionId = labelToActionId[virtualViewId]
+                val availableIds = AccessibilityActionsResourceIds.toMutableList()
+                val unassignedActions = mutableListOf<CustomAccessibilityAction>()
                 for (action in customActions) {
                     if (oldLabelToActionId!!.contains(action.label)) {
-                        var actionId = oldLabelToActionId[action.label]
+                        val actionId = oldLabelToActionId[action.label]
                         currentActionIdToLabel.put(actionId!!, action.label)
                         currentLabelToActionId[action.label] = actionId
                         availableIds.remove(actionId)
@@ -255,7 +275,7 @@
                     }
                 }
                 for ((index, action) in unassignedActions.withIndex()) {
-                    var actionId = availableIds[index]
+                    val actionId = availableIds[index]
                     currentActionIdToLabel.put(actionId, action.label)
                     currentLabelToActionId[action.label] = actionId
                     info.addAction(
@@ -266,7 +286,7 @@
                 }
             } else {
                 for ((index, action) in customActions.withIndex()) {
-                    var actionId = AccessibilityActionsResourceIds[index]
+                    val actionId = AccessibilityActionsResourceIds[index]
                     currentActionIdToLabel.put(actionId, action.label)
                     currentLabelToActionId[action.label] = actionId
                     info.addAction(
@@ -305,8 +325,9 @@
      * @return Whether this virtual view actually took accessibility focus.
      */
     private fun requestAccessibilityFocus(virtualViewId: Int): Boolean {
-        if (!accessibilityManager.isEnabled() ||
-            !accessibilityManager.isTouchExplorationEnabled()) {
+        if (!accessibilityManager.isEnabled ||
+            !accessibilityManager.isTouchExplorationEnabled
+        ) {
             return false
         }
         // TODO: Check virtual view visibility.
@@ -343,9 +364,9 @@
      * You should call this method after performing a user action that normally
      * fires an accessibility event, such as clicking on an item.
      *
-     * <pre>public void performItemClick(T item) {
+     * <pre>public performItemClick(T item) {
      *   ...
-     *   sendEventForVirtualViewId(item.id, AccessibilityEvent.TYPE_VIEW_CLICKED)
+     *   sendEventForVirtualView(item.id, AccessibilityEvent.TYPE_VIEW_CLICKED)
      * }
      * </pre>
      *
@@ -355,13 +376,13 @@
      * @param contentDescription Content description of this event.
      * @return true if the event was sent successfully.
      */
-    fun sendEventForVirtualView(
+    private fun sendEventForVirtualView(
         virtualViewId: Int,
         eventType: Int,
-        contentChangeType: Int?,
-        contentDescription: CharSequence?
+        contentChangeType: Int? = null,
+        contentDescription: CharSequence? = null
     ): Boolean {
-        if ((virtualViewId == InvalidId) || !accessibilityManager.isEnabled()) {
+        if ((virtualViewId == InvalidId) || !accessibilityManager.isEnabled) {
             return false
         }
 
@@ -374,6 +395,7 @@
         if (contentDescription != null) {
             event.contentDescription = contentDescription
         }
+
         return parent.requestSendAccessibilityEvent(view, event)
     }
 
@@ -393,7 +415,7 @@
         event.className = ClassName
 
         // Don't allow the client to override these properties.
-        event.packageName = view.getContext().getPackageName()
+        event.packageName = view.context.packageName
         event.setSource(view, virtualViewId)
 
         return event
@@ -426,7 +448,7 @@
         action: Int,
         arguments: Bundle?
     ): Boolean {
-        var node: SemanticsNode
+        val node: SemanticsNode
         if (virtualViewId == AccessibilityNodeProviderCompat.HOST_VIEW_ID) {
             node = view.semanticsOwner.rootSemanticsNode
         } else {
@@ -465,13 +487,17 @@
             }
             android.R.id.accessibilityActionSetProgress -> {
                 if (arguments == null || !arguments.containsKey(
-                        AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE)) {
+                        AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE
+                    )
+                ) {
                     return false
                 }
                 return if (node.canPerformAction(SemanticsActions.SetProgress)) {
                     node.config[SemanticsActions.SetProgress].action(
                         arguments.getFloat(
-                            AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE))
+                            AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE
+                        )
+                    )
                 } else {
                     false
                 }
@@ -515,7 +541,7 @@
             return false
         }
 
-        when (event.getAction()) {
+        when (event.action) {
             MotionEvent.ACTION_HOVER_MOVE, MotionEvent.ACTION_HOVER_ENTER -> {
                 val virtualViewId: Int = getVirtualViewAt(event.getX(), event.getY())
                 updateHoveredVirtualView(virtualViewId)
@@ -535,8 +561,8 @@
     }
 
     private fun getVirtualViewAt(x: Float, y: Float): Int {
-        var node = view.semanticsOwner.rootSemanticsNode
-        var id = findVirtualViewAt(x + node.globalBounds.left,
+        val node = view.semanticsOwner.rootSemanticsNode
+        val id = findVirtualViewAt(x + node.globalBounds.left,
             y + node.globalBounds.top, node)
         if (id == node.id) {
             return AccessibilityNodeProviderCompat.HOST_VIEW_ID
@@ -547,7 +573,7 @@
     // TODO(b/151729467): compose accessibility getVirtualViewAt needs to be more efficient
     private fun findVirtualViewAt(x: Float, y: Float, node: SemanticsNode): Int {
         node.children.fastForEach {
-            var id = findVirtualViewAt(x, y, it)
+            val id = findVirtualViewAt(x, y, it)
             if (id != InvalidId) {
                 return id
             }
@@ -620,6 +646,110 @@
     // TODO (in a separate cl): Called when the SemanticsNode with id semanticsNodeId disappears.
     // fun clearNode(semanticsNodeId: Int) { // clear the actionIdToId and labelToActionId nodes }
 
+    internal fun onSemanticsChange() {
+        if (accessibilityManager.isEnabled && !checkingForSemanticsChanges) {
+            checkingForSemanticsChanges = true
+            handler.post {
+                checkForSemanticsChanges()
+                checkingForSemanticsChanges = false
+            }
+        }
+    }
+
+    private fun checkForSemanticsChanges() {
+        val newSemanticsNodes = view.semanticsOwner.getAllSemanticsNodesToMap()
+
+        // Structural change
+        sendSemanticsStructureChangeEvents(view.semanticsOwner.rootSemanticsNode, semanticsRoot)
+
+        // Property change
+        sendSemanticsPropertyChangeEvents(newSemanticsNodes)
+
+        // Update the cache
+        semanticsNodes.clear()
+        for (entry in newSemanticsNodes.entries) {
+            semanticsNodes[entry.key] = SemanticsNodeCopy(entry.value)
+        }
+        semanticsRoot = SemanticsNodeCopy(view.semanticsOwner.rootSemanticsNode)
+    }
+
+    private fun sendSemanticsPropertyChangeEvents(newSemanticsNodes: Map<Int, SemanticsNode>) {
+        for (id in newSemanticsNodes.keys) {
+            if (!semanticsNodes.contains(id)) {
+                continue
+            }
+
+            // We do doing this search because the new configuration is set as a whole, so we
+            // can't indicate which property is changed when setting the new configuration.
+            val newNode = newSemanticsNodes[id]
+            val oldNode = semanticsNodes[id]
+            for (entry in newNode!!.config) {
+                if (entry.value == oldNode!!.config.getOrNull(entry.key)) {
+                    continue
+                }
+                when (entry.key) {
+                    // we are in aosp, so can't use the state description yet.
+                    SemanticsProperties.AccessibilityValue,
+                    SemanticsProperties.AccessibilityLabel ->
+                        sendEventForVirtualView(
+                            semanticsNodeIdToAccessibilityVirtualNodeId(id),
+                            AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+                            AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
+                            entry.value as CharSequence
+                        )
+                    else -> {
+                        // TODO(b/151840490) send the correct events when property changes
+                    }
+                }
+            }
+        }
+    }
+
+    private fun sendSemanticsStructureChangeEvents(
+        newNode: SemanticsNode,
+        oldNode: SemanticsNodeCopy
+    ) {
+        val newChildren: MutableSet<Int> = mutableSetOf()
+
+        // If any child is added, clear the subtree rooted at this node and return.
+        newNode.children.fastForEach { child ->
+            if (!oldNode.children.contains(child.id)) {
+                sendEventForVirtualView(
+                    semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
+                    AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+                    AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
+                    null
+                )
+                return
+            }
+            newChildren.add(child.id)
+        }
+
+        // If any child is deleted, clear the subtree rooted at this node and return.
+        for (child in oldNode.children) {
+            if (!newChildren.contains(child)) {
+                sendEventForVirtualView(
+                    semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
+                    AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+                    AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
+                    null
+                )
+                return
+            }
+        }
+
+        newNode.children.fastForEach { child ->
+            sendSemanticsStructureChangeEvents(child, semanticsNodes[child.id]!!)
+        }
+    }
+
+    private fun semanticsNodeIdToAccessibilityVirtualNodeId(id: Int): Int {
+        if (id == view.semanticsOwner.rootSemanticsNode.id) {
+            return AccessibilityNodeProviderCompat.HOST_VIEW_ID
+        }
+        return id
+    }
+
     inner class MyNodeProvider() : AccessibilityNodeProviderCompat() {
         override fun createAccessibilityNodeInfo(virtualViewId: Int):
                 AccessibilityNodeInfoCompat? {
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
index 66dec2d..d55e4b3 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
@@ -27,8 +27,8 @@
  * [LayoutNodeWrapper] with default implementations for methods.
  */
 internal open class DelegatingLayoutNodeWrapper<T : Modifier.Element>(
-    override val wrapped: LayoutNodeWrapper,
-    val modifier: T
+    override var wrapped: LayoutNodeWrapper,
+    open var modifier: T
 ) : LayoutNodeWrapper(wrapped.layoutNode) {
     override val providedAlignmentLines: Set<AlignmentLine>
         get() = wrapped.providedAlignmentLines
@@ -39,10 +39,27 @@
 
     override val measureScope: MeasureScope get() = wrapped.measureScope
 
+    /**
+     * Indicates that this modifier is used in [wrappedBy] also.
+     */
+    var isChained = false
+
     init {
         wrapped.wrappedBy = this
     }
 
+    /**
+     * Sets the modifier instance to the new modifier. [modifier] must be the
+     * same type as the current modifier.
+     */
+    fun setModifierTo(modifier: Modifier.Element) {
+        if (modifier !== this.modifier) {
+            require(modifier.javaClass == this.modifier.javaClass)
+            @Suppress("UNCHECKED_CAST")
+            this.modifier = modifier as T
+        }
+    }
+
     override fun draw(canvas: Canvas) {
         withPositionTranslation(canvas) {
             wrapped.draw(canvas)
@@ -135,13 +152,11 @@
     override val parentData: Any? get() = wrapped.parentData
 
     override fun attach() {
-        wrapped.attach()
         _isAttached = true
     }
 
     override fun detach() {
         _isAttached = false
-        wrapped.detach()
     }
 }
 
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt
index fdb1cc0..929b6f5 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt
@@ -28,7 +28,6 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntOffset
 import androidx.ui.util.fastAny
-import androidx.ui.util.fastFirstOrNull
 import androidx.ui.util.fastForEach
 
 internal class InnerPlaceable(
@@ -58,13 +57,7 @@
     }
 
     override val parentData: Any?
-        @Suppress("DEPRECATION")
-        get() = if (layoutNode.handlesParentData) {
-            null
-        } else {
-            layoutNode.children
-                .fastFirstOrNull { it.parentData != null }?.parentData
-        }
+        get() = null
 
     override fun findPreviousFocusWrapper() = wrappedBy?.findPreviousFocusWrapper()
 
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt
index 3b96373..9bd3871 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt
@@ -34,6 +34,13 @@
     // Do not invalidate itself on position change.
     override val invalidateLayerOnBoundsChange get() = false
 
+    override var modifier: DrawLayerModifier
+        get() = super.modifier
+        set(value) {
+            super.modifier = value
+            _layer?.modifier = value
+        }
+
     private val invalidateParentLayer: () -> Unit = {
         wrappedBy?.findLayer()?.invalidate()
     }
@@ -161,4 +168,8 @@
             hitPointerInputFilters
         )
     }
+
+    override fun onModifierChanged() {
+        _layer?.invalidate()
+    }
 }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt
index 0449125..2b4d393 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt
@@ -16,27 +16,26 @@
 
 package androidx.ui.core
 
-import android.content.Context
 import androidx.compose.Composable
+import androidx.compose.ComposableContract
 import androidx.compose.Composition
 import androidx.compose.CompositionReference
 import androidx.compose.ExperimentalComposeApi
 import androidx.compose.FrameManager
 import androidx.compose.Recomposer
 import androidx.compose.Stable
-import androidx.compose.Untracked
 import androidx.compose.compositionReference
 import androidx.compose.currentComposer
+import androidx.compose.emit
 import androidx.compose.onDispose
 import androidx.compose.remember
 import androidx.ui.core.LayoutNode.LayoutState
+import androidx.ui.node.UiApplier
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntOffset
 import androidx.ui.unit.IntSize
 import androidx.ui.util.fastForEach
-import androidx.ui.util.fastMap
-import androidx.ui.util.fastMaxBy
 import kotlin.math.max
 
 /**
@@ -164,9 +163,15 @@
     measureBlocks: LayoutNode.MeasureBlocks,
     modifier: Modifier
 ) {
-    LayoutNode(modifier = currentComposer.materialize(modifier), measureBlocks = measureBlocks) {
-        children()
-    }
+    val materialized = currentComposer.materialize(modifier)
+    emit<LayoutNode, UiApplier>(
+        ctor = LayoutEmitHelper.constructor,
+        update = {
+            set(materialized, LayoutEmitHelper.setModifier)
+            set(measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+        },
+        children = children
+    )
 }
 
 @Composable
@@ -178,42 +183,17 @@
     measureBlock: MeasureBlock
 ) {
     val measureBlocks = remember(measureBlock) { MeasuringIntrinsicsMeasureBlocks(measureBlock) }
-    LayoutNode(
-        modifier = currentComposer.materialize(modifier),
-        measureBlocks = measureBlocks,
-        canMultiMeasure =
-        true
-    ) {
-        children()
-    }
-}
-
-@Composable
-@Deprecated("This composable supports our transition from single child composables to modifiers. " +
-        "It should not be used in app code directly.")
-fun PassThroughLayout(
-    modifier: Modifier = Modifier,
-    children: @Composable () -> Unit
-) {
-    val measureBlocks = remember {
-        val measureBlock: MeasureBlock = { measurables, constraints, _ ->
-            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(0, 0) }
-            }
-        }
-        MeasuringIntrinsicsMeasureBlocks(measureBlock)
-    }
-    LayoutNode(
-        modifier = currentComposer.materialize(modifier),
-        measureBlocks = measureBlocks,
-        handlesParentData = false,
-        useChildZIndex = true
-    ) {
-        children()
-    }
+    val materialized = currentComposer.materialize(modifier)
+    emit<LayoutNode, UiApplier>(
+        ctor = LayoutEmitHelper.constructor,
+        update = {
+            set(materialized, LayoutEmitHelper.setModifier)
+            set(measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+            @Suppress("DEPRECATION")
+            set(Unit) { this.canMultiMeasure = true }
+        },
+        children = children
+    )
 }
 
 /**
@@ -463,7 +443,6 @@
 ) {
     val state = remember { WithConstrainsState() }
     state.children = children
-    state.context = ContextAmbient.current
     // TODO(lmr): refactor these APIs so that recomposer isn't necessary
     @OptIn(ExperimentalComposeApi::class)
     state.recomposer = currentComposer.recomposer
@@ -471,10 +450,14 @@
     // if this code was executed subcomposition must be triggered as well
     state.forceRecompose = true
 
-    LayoutNode(
-        modifier = currentComposer.materialize(modifier),
-        ref = state.nodeRef,
-        measureBlocks = state.measureBlocks
+    val materialized = currentComposer.materialize(modifier)
+    emit<LayoutNode, UiApplier>(
+        ctor = LayoutEmitHelper.constructor,
+        update = {
+            set(materialized, LayoutEmitHelper.setModifier)
+            set(state.measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+            set(state.nodeRef, LayoutEmitHelper.setRef)
+        }
     )
 
     // if LayoutNode scheduled the remeasuring no further steps are needed - subcomposition
@@ -535,7 +518,6 @@
 private class WithConstrainsState {
     lateinit var recomposer: Recomposer
     var compositionRef: CompositionReference? = null
-    lateinit var context: Context
     val nodeRef = Ref<LayoutNode>()
     var children: @Composable WithConstraintsScope.() -> Unit = { }
     var forceRecompose = false
@@ -590,9 +572,13 @@
 
     @OptIn(ExperimentalComposeApi::class)
     fun subcompose() {
-        // TODO(b/150390669): Review use of @Untracked
+        // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
         composition =
-            subcomposeInto(context, nodeRef.value!!, recomposer, compositionRef) @Untracked {
+            subcomposeInto(
+                nodeRef.value!!,
+                recomposer,
+                compositionRef
+            ) @ComposableContract(tracked = false) {
                 scope.children()
             }
         forceRecompose = false
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt
index f389a47..b8e76fd 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt
@@ -72,7 +72,7 @@
 
     /**
      * Returns the position of an [alignment line][AlignmentLine],
-     * or `null` if the line is not provided.
+     * or [AlignmentLine.Unspecified] if the line is not provided.
      */
     operator fun get(line: AlignmentLine): Int
 }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt
index f792361..e830aa7 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt
@@ -90,6 +90,12 @@
         get() = requireOwner().measureIteration == outerMeasurablePlaceable.measureIteration
 
     /**
+     * A cache of modifiers to be used when setting and reusing previous modifiers.
+     */
+    private var wrapperCache = emptyArray<DelegatingLayoutNodeWrapper<*>?>()
+    private var wrapperCacheCount = 0
+
+    /**
      * 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].
      */
@@ -179,7 +185,7 @@
 
         requestRemeasure()
         parent?.requestRemeasure()
-        outerLayoutNodeWrapper.attach()
+        forEachDelegate { it.attach() }
         onAttach?.invoke(owner)
     }
 
@@ -198,7 +204,7 @@
         alignmentLinesQueryOwner = null
         alignmentUsageByParent = UsageByParent.NotUsed
         onDetach?.invoke(owner)
-        outerLayoutNodeWrapper.detach()
+        forEachDelegate { it.detach() }
 
         if (outerSemantics != null) {
             owner.onSemanticsChange()
@@ -465,20 +471,7 @@
      * this features.
      */
     internal val zIndex: Float
-        get() {
-            @Suppress("DEPRECATION")
-            return if (useChildZIndex) {
-                // While some temporary components for adding semantics have to add
-                // PassThroughLayout it breaks zIndex calculation via adding extra layout layer.
-                // To workaround it we use the zIndex of the first child of PassThroughLayout
-                children.firstOrNull()?.zIndex ?: 0f
-            } else {
-                outerZIndexModifier?.zIndex ?: 0f
-            }
-        }
-
-    @Deprecated("To be removed when we remove PassThroughLayout")
-    internal var useChildZIndex = false
+        get() = outerZIndexModifier?.zIndex ?: 0f
 
     /**
      * The outermost ZIndexModifier in the modifier chain or `null` if there are no
@@ -507,6 +500,8 @@
             if (value == field) return
             field = value
 
+            copyWrappersToCache()
+
             // Rebuild layoutNodeWrapper
             val oldOuterWrapper = outerMeasurablePlaceable.outerWrapper
             if (outerSemantics != null && isAttached()) {
@@ -517,65 +512,95 @@
             onChildPositionedCallbacks.clear()
             outerZIndexModifier = null
             innerLayerWrapper = null
+
+            // Create a new chain of LayoutNodeWrappers, reusing existing ones from wrappers
+            // when possible.
             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
-                // that implements both DrawModifier and LayoutModifier will have it's draw bounds
-                // reflect the dimensions defined by the LayoutModifier.
                 if (mod is OnPositionedModifier) {
                     onPositionedCallbacks += mod
                 }
                 if (mod is OnChildPositionedModifier) {
                     onChildPositionedCallbacks += mod
                 }
-                if (mod is DrawModifier) {
-                    wrapper = ModifiedDrawNode(wrapper, mod)
-                }
-                if (mod is DrawLayerModifier) {
-                    val layerWrapper = LayerWrapper(wrapper, mod)
-                    wrapper = layerWrapper
-                    if (innerLayerWrapper == null) {
-                        innerLayerWrapper = layerWrapper
-                    }
-                }
-                if (mod is FocusModifier) {
-                    require(mod is FocusModifierImpl)
-                    wrapper = ModifiedFocusNode(wrapper, mod).also { mod.focusNode = it }
-                }
-                if (mod is KeyInputModifier) {
-                    wrapper = ModifiedKeyInputNode(wrapper, mod).also { mod.keyInputNode = it }
-                }
-                if (mod is PointerInputModifier) {
-                    wrapper = PointerInputDelegatingWrapper(wrapper, mod)
-                }
-                if (mod is LayoutModifier) {
-                    wrapper = ModifiedLayoutNode(wrapper, mod)
-                }
-                if (mod is ParentDataModifier) {
-                    wrapper = ModifiedParentDataNode(wrapper, mod)
-                }
-                if (mod is SemanticsModifier) {
-                    wrapper = SemanticsWrapper(wrapper, mod)
-                    if (isAttached()) {
-                        owner!!.onSemanticsChange()
-                    }
-                }
                 if (mod is ZIndexModifier) {
                     outerZIndexModifier = mod
                 }
+
+                val delegate = reuseLayoutNodeWrapper(mod, toWrap)
+                if (delegate != null) {
+                    wrapper = delegate
+                } else {
+                    // The order in which the following blocks occur matters. For example, the
+                    // DrawModifier block should be before the LayoutModifier block so that a
+                    // Modifier that implements both DrawModifier and LayoutModifier will have
+                    // it's draw bounds reflect the dimensions defined by the LayoutModifier.
+                    if (mod is DrawModifier) {
+                        wrapper = ModifiedDrawNode(wrapper, mod)
+                    }
+                    if (mod is DrawLayerModifier) {
+                        val layerWrapper = LayerWrapper(wrapper, mod).assignChained(toWrap)
+                        wrapper = layerWrapper
+                        if (innerLayerWrapper == null) {
+                            innerLayerWrapper = layerWrapper
+                        }
+                    }
+                    if (mod is FocusModifier) {
+                        require(mod is FocusModifierImpl)
+                        wrapper = ModifiedFocusNode(wrapper, mod).also { mod.focusNode = it }
+                            .assignChained(toWrap)
+                    }
+                    if (mod is KeyInputModifier) {
+                        wrapper = ModifiedKeyInputNode(wrapper, mod).also { mod.keyInputNode = it }
+                            .assignChained(toWrap)
+                    }
+                    if (mod is PointerInputModifier) {
+                        wrapper = PointerInputDelegatingWrapper(wrapper, mod).assignChained(toWrap)
+                    }
+                    if (mod is LayoutModifier) {
+                        wrapper = ModifiedLayoutNode(wrapper, mod).assignChained(toWrap)
+                    }
+                    if (mod is ParentDataModifier) {
+                        wrapper = ModifiedParentDataNode(wrapper, mod).assignChained(toWrap)
+                    }
+                    if (mod is SemanticsModifier) {
+                        wrapper = SemanticsWrapper(wrapper, mod).assignChained(toWrap)
+                    }
+                }
                 wrapper
             }
+
             outerWrapper.wrappedBy = parent?.innerLayoutNodeWrapper
             outerMeasurablePlaceable.outerWrapper = outerWrapper
+
+            if (isAttached()) {
+                // call detach() on all removed LayoutNodeWrappers
+                for (i in 0 until wrapperCacheCount) {
+                    wrapperCache[i]?.detach()
+                }
+
+                // attach() all new LayoutNodeWrappers
+                forEachDelegate {
+                    if (!it.isAttached) {
+                        it.attach()
+                    }
+                }
+            }
+            for (i in 0 until wrapperCacheCount) {
+                wrapperCache[i] = null
+            }
+            wrapperCacheCount = 0
+
+            // call onModifierChanged() on all LayoutNodeWrappers
+            forEachDelegate { it.onModifierChanged() }
+
             // 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 (oldOuterWrapper != outerWrapper) {
-                oldOuterWrapper.detach()
+            if (oldOuterWrapper != innerLayoutNodeWrapper ||
+                outerWrapper != innerLayoutNodeWrapper) {
                 requestRemeasure()
                 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.
@@ -584,12 +609,6 @@
             owner?.onInvalidate(this)
         }
 
-    @Deprecated(
-        "Temporary API to support our transition from single child composables to modifiers."
-    )
-    // TODO(popam): remove this
-    var handlesParentData: Boolean = true
-
     /**
      * Coordinates of just the contents of the LayoutNode, after being affected by all modifiers.
      */
@@ -893,9 +912,7 @@
      */
     fun getModifierInfo(): List<ModifierInfo> {
         val infoList = mutableListOf<ModifierInfo>()
-        var wrapper = outerLayoutNodeWrapper
-
-        while (wrapper != innerLayoutNodeWrapper) {
+        forEachDelegate { wrapper ->
             val info = if (wrapper is LayerWrapper) {
                 ModifierInfo(wrapper.modifier, wrapper, wrapper.layer)
             } else {
@@ -903,11 +920,95 @@
                 ModifierInfo(wrapper.modifier, wrapper)
             }
             infoList += info
-            wrapper = wrapper.wrapped!!
         }
         return infoList
     }
 
+    /**
+     * Reuses a [DelegatingLayoutNodeWrapper] from [wrapperCache] if one matches the class
+     * type of [modifier]. This walks backward through the [wrapperCache] and
+     * extracts all [DelegatingLayoutNodeWrapper]s that are
+     * [chained][DelegatingLayoutNodeWrapper.isChained] together.
+     * If none can be reused, `null` is returned.
+     */
+    private fun reuseLayoutNodeWrapper(
+        modifier: Modifier.Element,
+        wrapper: LayoutNodeWrapper
+    ): DelegatingLayoutNodeWrapper<*>? {
+        if (wrapperCacheCount == 0) {
+            return null
+        }
+        val index = lastMatchingModifierIndex(modifier)
+
+        if (index < 0) {
+            return null
+        }
+
+        val endWrapper = removeFromWrapperCache(index)
+        var startWrapper = endWrapper
+        var chainedIndex = index
+        startWrapper.setModifierTo(modifier)
+        if (innerLayerWrapper == null && startWrapper is LayerWrapper) {
+            innerLayerWrapper = startWrapper
+        }
+
+        while (startWrapper.isChained) {
+            chainedIndex--
+            startWrapper = removeFromWrapperCache(chainedIndex)
+            startWrapper.setModifierTo(modifier)
+            if (innerLayerWrapper == null && startWrapper is LayerWrapper) {
+                innerLayerWrapper = startWrapper
+            }
+        }
+
+        endWrapper.wrapped = wrapper
+        wrapper.wrappedBy = endWrapper
+        return startWrapper
+    }
+
+    private fun lastMatchingModifierIndex(modifier: Modifier): Int {
+        var index = wrapperCacheCount - 1
+        while (index >= 0) {
+            val wrapper = wrapperCache[index]
+            if (wrapper != null && (wrapper.modifier === modifier ||
+                        wrapper.modifier.javaClass == modifier.javaClass)) {
+                    return index
+            }
+            index--
+        }
+        return -1
+    }
+
+    private fun removeFromWrapperCache(index: Int): DelegatingLayoutNodeWrapper<*> {
+        val wrapper = wrapperCache[index]!!
+        wrapperCache[index] = null
+        if (index == wrapperCacheCount - 1) {
+            wrapperCacheCount--
+        }
+        return wrapper
+    }
+
+    /**
+     * Copies all [DelegatingLayoutNodeWrapper]s currently in use and returns them in a new
+     * Array.
+     */
+    private fun copyWrappersToCache() {
+        // first count them:
+        var count = 0
+        forEachDelegate { count++ }
+        if (count == 0) {
+            return
+        }
+        if (wrapperCache.size < count) {
+            wrapperCache = arrayOfNulls(count)
+        }
+        wrapperCacheCount = count
+        var i = 0
+        forEachDelegate {
+            wrapperCache[i++] = it as DelegatingLayoutNodeWrapper<*>
+        }
+    }
+
     // Delegation from Measurable to measurableAndPlaceable
     override fun measure(constraints: Constraints, layoutDirection: LayoutDirection) =
         outerMeasurablePlaceable.measure(constraints, layoutDirection)
@@ -934,6 +1035,18 @@
     override fun maxIntrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int =
         outerMeasurablePlaceable.maxIntrinsicHeight(width, layoutDirection)
 
+    /**
+     * Calls [block] on all [DelegatingLayoutNodeWrapper]s in the LayoutNodeWrapper chain.
+     */
+    private inline fun forEachDelegate(block: (LayoutNodeWrapper) -> Unit) {
+        var delegate = outerLayoutNodeWrapper
+        val inner = innerLayoutNodeWrapper
+        while (delegate != inner) {
+            block(delegate)
+            delegate = delegate.wrapped!!
+        }
+    }
+
     internal companion object {
         private val ErrorMeasureBlocks = object : NoIntrinsicsMeasureBlocks(
             error = "Undefined intrinsics block and it is required"
@@ -982,6 +1095,17 @@
 }
 
 /**
+ * Object of pre-allocated lambdas used to make emits to LayoutNodes allocation-less.
+ */
+internal object LayoutEmitHelper {
+    val constructor: () -> LayoutNode = { LayoutNode() }
+    val setModifier: LayoutNode.(Modifier) -> Unit = { this.modifier = it }
+    val setMeasureBlocks: LayoutNode.(LayoutNode.MeasureBlocks) -> Unit =
+        { this.measureBlocks = it }
+    val setRef: LayoutNode.(Ref<LayoutNode>) -> Unit = { this.ref = it }
+}
+
+/**
  * Comparator allowing to sort nodes by zIndex
  */
 private val ZIndexComparator = Comparator<LayoutNode> { node1, node2 ->
@@ -1075,3 +1199,20 @@
     override val layoutDirection: LayoutDirection
         get() = wrapped!!.measureScope.layoutDirection
 }
+
+/**
+ * Sets [DelegatingLayoutNodeWrapper#isChained] to `true` of the [wrapped] when it
+ * is part of a chain of LayoutNodes for the same modifier.
+ *
+ * @param originalWrapper The LayoutNodeWrapper that the modifier chain should be wrapping.
+ */
+@Suppress("NOTHING_TO_INLINE")
+private inline fun <T : DelegatingLayoutNodeWrapper<*>> T.assignChained(
+    originalWrapper: LayoutNodeWrapper
+): T {
+    if (originalWrapper !== wrapped) {
+        var wrapper = wrapped as DelegatingLayoutNodeWrapper<*>
+        wrapper.isChained = true
+    }
+    return this
+}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt
index 0a761c0..7e56b29 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt
@@ -376,6 +376,12 @@
      */
     abstract fun findLastKeyInputWrapper(): ModifiedKeyInputNode?
 
+    /**
+     * Called when [LayoutNode.modifier] has changed and all the LayoutNodeWrappers have been
+     * configured.
+     */
+    open fun onModifierChanged() {}
+
     internal companion object {
         const val ExpectAttachedLayoutCoordinates = "LayoutCoordinate operations are only valid " +
                 "when isAttached is true"
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt
index 9d4e4d0..753df72 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt
@@ -57,10 +57,16 @@
                 // `onRequestMeasure` will be called for all items in `postponedMeasureRequests`
                 return true
             }
-            if (layoutState == LayoutState.NeedsRemeasure ||
-                layoutState == LayoutState.NeedsRelayout) {
-                // remeasure or relayout is scheduled
-                return relayoutNodes.contains(this)
+            // remeasure or relayout is scheduled
+            val parentLayoutState = parent?.layoutState
+            if (layoutState == LayoutState.NeedsRemeasure) {
+                return relayoutNodes.contains(this) ||
+                        parentLayoutState == LayoutState.NeedsRemeasure
+            }
+            if (layoutState == LayoutState.NeedsRelayout) {
+                return relayoutNodes.contains(this) ||
+                        parentLayoutState == LayoutState.NeedsRemeasure ||
+                        parentLayoutState == LayoutState.NeedsRelayout
             }
         }
         return true
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt
index 6da999b..4b685eb 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt
@@ -129,7 +129,10 @@
             } else {
                 layoutNode.layoutState = NeedsRemeasure
                 if (layoutNode.isPlaced || layoutNode.canAffectPlacedParent) {
-                    relayoutNodes.add(layoutNode)
+                    val parentLayoutState = layoutNode.parent?.layoutState
+                    if (parentLayoutState != NeedsRemeasure) {
+                        relayoutNodes.add(layoutNode)
+                    }
                 }
             }
             !duringMeasureLayout
@@ -152,7 +155,10 @@
         Ready -> {
             layoutNode.layoutState = NeedsRelayout
             if (layoutNode.isPlaced) {
-                relayoutNodes.add(layoutNode)
+                val parentLayoutState = layoutNode.parent?.layoutState
+                if (parentLayoutState != NeedsRemeasure && parentLayoutState != NeedsRelayout) {
+                    relayoutNodes.add(layoutNode)
+                }
             }
             !duringMeasureLayout
         }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt
index 5abf9d5..aca0bc1 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt
@@ -22,40 +22,40 @@
 import androidx.ui.graphics.PaintingStyle
 internal class ModifiedLayoutNode(
     wrapped: LayoutNodeWrapper,
-    private val layoutModifier: LayoutModifier
-) : DelegatingLayoutNodeWrapper<LayoutModifier>(wrapped, layoutModifier) {
+    modifier: LayoutModifier
+) : DelegatingLayoutNodeWrapper<LayoutModifier>(wrapped, modifier) {
 
     override val measureScope = ModifierMeasureScope()
 
     override fun performMeasure(
         constraints: Constraints,
         layoutDirection: LayoutDirection
-    ): Placeable = with(layoutModifier) {
+    ): Placeable = with(modifier) {
         measureScope.layoutDirection = layoutDirection
         measureResult = measureScope.measure(wrapped, constraints, layoutDirection)
         this@ModifiedLayoutNode
     }
 
     override fun minIntrinsicWidth(height: Int, layoutDirection: LayoutDirection): Int =
-        with(layoutModifier) {
+        with(modifier) {
             measureScope.layoutDirection = layoutDirection
             measureScope.minIntrinsicWidth(wrapped, height, layoutDirection)
         }
 
     override fun maxIntrinsicWidth(height: Int, layoutDirection: LayoutDirection): Int =
-        with(layoutModifier) {
+        with(modifier) {
             measureScope.layoutDirection = layoutDirection
             measureScope.maxIntrinsicWidth(wrapped, height, layoutDirection)
         }
 
     override fun minIntrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int =
-        with(layoutModifier) {
+        with(modifier) {
             measureScope.layoutDirection = layoutDirection
             measureScope.minIntrinsicHeight(wrapped, width, layoutDirection)
         }
 
     override fun maxIntrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int =
-        with(layoutModifier) {
+        with(modifier) {
             measureScope.layoutDirection = layoutDirection
             measureScope.maxIntrinsicHeight(wrapped, width, layoutDirection)
         }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt
index 6190494..2001b81 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt
@@ -33,6 +33,11 @@
     val layerId: Long
 
     /**
+     * The DrawLayerModifier used in this layer.
+     */
+    var modifier: DrawLayerModifier
+
+    /**
      * Reads the [DrawLayerModifier] and dirties the layer so that it will be redrawn.
      */
     fun updateLayerProperties()
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt
index 46d2a7a..253f6a7 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt
@@ -32,7 +32,6 @@
 import androidx.compose.ambientOf
 import androidx.compose.currentComposer
 import androidx.compose.emptyContent
-import androidx.compose.escapeCompose
 import androidx.compose.onCommit
 import androidx.compose.onDispose
 import androidx.compose.remember
@@ -161,16 +160,14 @@
 
     val popupPositionProperties = remember { PopupPositionProperties() }
     val popupLayout = remember(isFocusable) {
-        escapeCompose {
-            PopupLayout(
-                composeView = view,
-                popupIsFocusable = isFocusable,
-                onDismissRequest = onDismissRequest,
-                popupPositionProperties = popupPositionProperties,
-                popupPositionProvider = popupPositionProvider,
-                testTag = providedTestTag
-            )
-        }
+        PopupLayout(
+            composeView = view,
+            popupIsFocusable = isFocusable,
+            onDismissRequest = onDismissRequest,
+            popupPositionProperties = popupPositionProperties,
+            popupPositionProvider = popupPositionProvider,
+            testTag = providedTestTag
+        )
     }
     popupLayout.popupPositionProvider = popupPositionProvider
 
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt
index f032b4c..aeb05dc 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt
@@ -32,7 +32,7 @@
 @TargetApi(29)
 internal class RenderNodeLayer(
     val ownerView: AndroidComposeView,
-    val drawLayerModifier: DrawLayerModifier,
+    drawLayerModifier: DrawLayerModifier,
     val drawBlock: (Canvas) -> Unit,
     val invalidateParentLayer: () -> Unit
 ) : OwnedLayer {
@@ -61,22 +61,30 @@
     override val layerId: Long
         get() = renderNode.uniqueId
 
+    override var modifier: DrawLayerModifier = drawLayerModifier
+        set(value) {
+            if (field !== value) {
+                field = value
+                updateLayerProperties()
+            }
+        }
+
     override fun updateLayerProperties() {
-        transformOrigin = drawLayerModifier.transformOrigin
+        transformOrigin = modifier.transformOrigin
         val wasClippingManually = renderNode.clipToOutline && outlineResolver.clipPath != null
-        renderNode.scaleX = drawLayerModifier.scaleX
-        renderNode.scaleY = drawLayerModifier.scaleY
-        renderNode.alpha = drawLayerModifier.alpha
-        renderNode.translationX = drawLayerModifier.translationX
-        renderNode.translationY = drawLayerModifier.translationY
-        renderNode.elevation = drawLayerModifier.shadowElevation
-        renderNode.rotationZ = drawLayerModifier.rotationZ
-        renderNode.rotationX = drawLayerModifier.rotationX
-        renderNode.rotationY = drawLayerModifier.rotationY
+        renderNode.scaleX = modifier.scaleX
+        renderNode.scaleY = modifier.scaleY
+        renderNode.alpha = modifier.alpha
+        renderNode.translationX = modifier.translationX
+        renderNode.translationY = modifier.translationY
+        renderNode.elevation = modifier.shadowElevation
+        renderNode.rotationZ = modifier.rotationZ
+        renderNode.rotationX = modifier.rotationX
+        renderNode.rotationY = modifier.rotationY
         renderNode.pivotX = transformOrigin.pivotFractionX * renderNode.width
         renderNode.pivotY = transformOrigin.pivotFractionY * renderNode.height
-        val shape = drawLayerModifier.shape
-        val clip = drawLayerModifier.clip
+        val shape = modifier.shape
+        val clip = modifier.clip
         renderNode.clipToOutline = clip && shape !== RectangleShape
         renderNode.clipToBounds = clip && shape === RectangleShape
         val shapeChanged = outlineResolver.update(
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt
index 25532ba..084285b 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt
@@ -16,27 +16,12 @@
 
 package androidx.ui.core
 
-import androidx.compose.Composable
 import androidx.compose.Stable
 import androidx.ui.core.semantics.semantics
 import androidx.ui.semantics.SemanticsPropertyReceiver
 import androidx.ui.semantics.testTag
 
 /**
- * Applies a tag to allow this element to be found in tests.
- *
- * This is a convenience method for a [Semantics] that sets [SemanticsPropertyReceiver.testTag].
- */
-@Composable
-@Deprecated(message = "Use Modifier.testTag instead.")
-fun TestTag(tag: String, children: @Composable () -> Unit) {
-    @Suppress("DEPRECATION")
-    PassThroughLayout(
-        Modifier.semantics(applyToChildLayoutNode = true, properties = { testTag = tag }),
-        children)
-}
-
-/**
  * Applies a tag to allow modified element to be found in tests.
  *
  * This is a convenience method for a [semantics] that sets [SemanticsPropertyReceiver.testTag].
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt
index 8a697e6..a158617 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt
@@ -35,7 +35,7 @@
 internal class ViewLayer(
     val ownerView: AndroidComposeView,
     val container: ViewLayerContainer,
-    val drawLayerModifier: DrawLayerModifier,
+    drawLayerModifier: DrawLayerModifier,
     val drawBlock: (Canvas) -> Unit,
     val invalidateParentLayer: () -> Unit
 ) : View(ownerView.context), OwnedLayer {
@@ -49,6 +49,14 @@
     private var drawnWithZ = false
     private val canvasHolder = CanvasHolder()
 
+    override var modifier: DrawLayerModifier = drawLayerModifier
+        set(value) {
+            if (value !== field) {
+                field = value
+                updateLayerProperties()
+            }
+        }
+
     /**
      * Local copy of the transform origin as DrawLayerModifier can be implemented
      * as a model object. Update this field within [updateLayerProperties] and use it
@@ -66,20 +74,20 @@
         get() = id.toLong()
 
     override fun updateLayerProperties() {
-        this.mTransformOrigin = drawLayerModifier.transformOrigin
-        this.scaleX = drawLayerModifier.scaleX
-        this.scaleY = drawLayerModifier.scaleY
-        this.alpha = drawLayerModifier.alpha
-        this.translationX = drawLayerModifier.translationX
-        this.translationY = drawLayerModifier.translationY
-        this.elevation = drawLayerModifier.shadowElevation
-        this.rotation = drawLayerModifier.rotationZ
-        this.rotationX = drawLayerModifier.rotationX
-        this.rotationY = drawLayerModifier.rotationY
+        this.mTransformOrigin = modifier.transformOrigin
+        this.scaleX = modifier.scaleX
+        this.scaleY = modifier.scaleY
+        this.alpha = modifier.alpha
+        this.translationX = modifier.translationX
+        this.translationY = modifier.translationY
+        this.elevation = modifier.shadowElevation
+        this.rotation = modifier.rotationZ
+        this.rotationX = modifier.rotationX
+        this.rotationY = modifier.rotationY
         this.pivotX = mTransformOrigin.pivotFractionX * width
         this.pivotY = mTransformOrigin.pivotFractionY * height
-        val shape = drawLayerModifier.shape
-        val clip = drawLayerModifier.clip
+        val shape = modifier.shape
+        val clip = modifier.clip
         this.clipToBounds = clip && shape === RectangleShape
         resetClipBounds()
         val wasClippingManually = manualClipPath != null
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt
index e7f07d0..b9262c1 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt
@@ -16,7 +16,6 @@
 package androidx.ui.core
 
 import android.app.Activity
-import android.content.Context
 import android.os.Build
 import android.view.View
 import android.view.ViewGroup
@@ -26,8 +25,10 @@
 import androidx.compose.Composable
 import androidx.compose.Composition
 import androidx.compose.CompositionReference
+import androidx.compose.ExperimentalComposeApi
 import androidx.compose.FrameManager
 import androidx.compose.InternalComposeApi
+import androidx.compose.Providers
 import androidx.compose.Recomposer
 import androidx.compose.SlotTable
 import androidx.compose.compositionFor
@@ -36,7 +37,7 @@
 import androidx.lifecycle.LifecycleEventObserver
 import androidx.lifecycle.LifecycleOwner
 import androidx.ui.core.selection.SelectionContainer
-import androidx.ui.node.UiComposer
+import androidx.ui.node.UiApplier
 import java.util.Collections
 import java.util.WeakHashMap
 
@@ -47,19 +48,24 @@
  * @see Composition.dispose
  */
 // TODO: Remove this API when View/LayoutNode mixed trees work
+@OptIn(ExperimentalComposeApi::class)
 fun ViewGroup.setViewContent(
     parent: CompositionReference? = null,
     composable: @Composable () -> Unit
 ): Composition = compositionFor(
-    context = context,
-    container = this,
-    recomposer = Recomposer.current(),
-    parent = parent,
-    onBeforeFirstComposition = {
+    this,
+    UiApplier(this),
+    Recomposer.current(),
+    parent,
+    onCreated = {
         removeAllViews()
     }
 ).apply {
-    setContent(composable)
+    setContent {
+        Providers(ContextAmbient provides [email protected]) {
+            composable()
+        }
+    }
 }
 
 /**
@@ -87,13 +93,18 @@
 // nextFrame() inside recompose() doesn't really start a new frame, but a new subframe
 // instead.
 @MainThread
+@OptIn(ExperimentalComposeApi::class)
 fun subcomposeInto(
-    context: Context,
     container: LayoutNode,
     recomposer: Recomposer,
     parent: CompositionReference? = null,
     composable: @Composable () -> Unit
-): Composition = compositionFor(context, container, recomposer, parent).apply {
+): Composition = compositionFor(
+    container,
+    UiApplier(container),
+    recomposer,
+    parent
+).apply {
     setContent(composable)
 }
 
@@ -107,10 +118,9 @@
 @MainThread
 fun subcomposeInto(
     container: LayoutNode,
-    context: Context,
     parent: CompositionReference? = null,
     composable: @Composable () -> Unit
-): Composition = subcomposeInto(context, container, Recomposer.current(), parent, composable)
+): Composition = subcomposeInto(container, Recomposer.current(), parent, composable)
 
 /**
  * Composes the given composable into the given activity. The [content] will become the root view
@@ -134,7 +144,7 @@
         ?: AndroidOwner(this, this).also {
             setContentView(it.view, DefaultLayoutParams)
         }
-    return doSetContent(this, composeView, recomposer, content)
+    return doSetContent(composeView, recomposer, content)
 }
 
 /**
@@ -168,7 +178,7 @@
             removeAllViews(); null
         }
             ?: AndroidOwner(context).also { addView(it.view, DefaultLayoutParams) }
-    return doSetContent(context, composeView, recomposer, content)
+    return doSetContent(composeView, recomposer, content)
 }
 
 /**
@@ -191,7 +201,6 @@
 ): Composition = setContent(Recomposer.current(), content)
 
 private fun doSetContent(
-    context: Context,
     owner: AndroidOwner,
     recomposer: Recomposer,
     content: @Composable () -> Unit
@@ -200,7 +209,8 @@
         owner.view.setTag(R.id.inspection_slot_table_set,
                 Collections.newSetFromMap(WeakHashMap<SlotTable, Boolean>()))
     }
-    val original = compositionFor(context, owner.root, recomposer)
+    @OptIn(ExperimentalComposeApi::class)
+    val original = compositionFor(owner.root, UiApplier(owner.root), recomposer)
     val wrapped = owner.view.getTag(R.id.wrapped_composition_tag)
             as? WrappedComposition
         ?: WrappedComposition(owner, original).also {
@@ -270,23 +280,6 @@
     }
 }
 
-@Suppress("NAME_SHADOWING")
-private fun compositionFor(
-    context: Context,
-    container: Any,
-    recomposer: Recomposer,
-    parent: CompositionReference? = null,
-    onBeforeFirstComposition: (() -> Unit)? = null
-) = compositionFor(
-    container = container,
-    recomposer = recomposer,
-    parent = parent,
-    composerFactory = { slotTable, recomposer ->
-        onBeforeFirstComposition?.invoke()
-        UiComposer(context, container, slotTable, recomposer)
-    }
-)
-
 private val DefaultLayoutParams = ViewGroup.LayoutParams(
     ViewGroup.LayoutParams.WRAP_CONTENT,
     ViewGroup.LayoutParams.WRAP_CONTENT
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
index 801522c..29ccad2 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalPointerInput::class)
+
 package androidx.ui.core.gesture
 
 import androidx.compose.remember
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Direction
 import androidx.ui.core.Modifier
@@ -24,31 +28,46 @@
 import androidx.ui.core.PointerInputChange
 import androidx.ui.core.changedToUpIgnoreConsumed
 import androidx.ui.core.composed
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.positionChange
 import androidx.ui.geometry.Offset
 import androidx.ui.unit.IntSize
 
 /**
- * This gesture filter detects when the average distance change of all pointers surpasses touch
+ * This gesture filter detects when the average distance change of all pointers surpasses the touch
  * slop.
  *
  * The value of touch slop is currently defined internally as the constant [TouchSlop].
  *
- * @param onDragSlopExceeded Called when touch slop is exceeded in a supported direction. See
- * [canDrag].
- * @param canDrag Set to limit the directions under which touch slop can be exceeded. Return true
- * if you want a drag to be started due to the touch slop being surpassed in the given [Direction].
- * If [canDrag] is not provided, touch slop will be able to be exceeded in all directions.
+ * Note: [canDrag] and [orientation] interact such that [canDrag] will only be called for
+ * [Direction]s that are included in the given [orientation].
+ *
+ * Note: Changing the value of [orientation] will reset the gesture filter such that it will not
+ * respond to input until new pointers are detected.
+ *
+ * @param onDragSlopExceeded Called when touch slop is exceeded in a supported direction and
+ * orientation.
+ * @param canDrag Set to limit the types of directions under which touch slop can be exceeded.
+ * Return true if you want a drag to be started due to the touch slop being surpassed in the
+ * given [Direction]. If [canDrag] is not provided, touch slop will be able to be exceeded in all
+ * directions.
+ * @param orientation If provided, limits the [Direction]s that scroll slop can be exceeded in to
+ * those that are included in the given orientation and does not consider pointers that are locked
+ * to other orientations.
  */
 fun Modifier.dragSlopExceededGestureFilter(
     onDragSlopExceeded: () -> Unit,
-    canDrag: ((Direction) -> Boolean)? = null
+    canDrag: ((Direction) -> Boolean)? = null,
+    orientation: Orientation? = null
 ): Modifier = composed {
     val touchSlop = with(DensityAmbient.current) { TouchSlop.toPx() }
-    val filter = remember { DragSlopExceededGestureFilter(touchSlop) }
-    filter.canDrag = canDrag
+    val filter = remember {
+        DragSlopExceededGestureFilter(touchSlop)
+    }
     filter.onDragSlopExceeded = onDragSlopExceeded
+    filter.setDraggableData(orientation, canDrag)
     PointerInputModifierImpl(filter)
 }
 
@@ -61,80 +80,126 @@
     private var dyUnderSlop = 0f
     private var passedSlop = false
 
-    var canDrag: ((Direction) -> Boolean)? = null
+    private var canDrag: ((Direction) -> Boolean)? = null
+    private var orientation: Orientation? = null
+
     var onDragSlopExceeded: () -> Unit = {}
 
+    lateinit var scrollOrientationLocker: ScrollOrientationLocker
+    lateinit var customEventDispatcher: CustomEventDispatcher
+
+    fun setDraggableData(orientation: Orientation?, canDrag: ((Direction) -> Boolean)?) {
+        this.orientation = orientation
+        this.canDrag = { direction ->
+            when {
+                orientation == Orientation.Horizontal && direction == Direction.UP -> false
+                orientation == Orientation.Horizontal && direction == Direction.DOWN -> false
+                orientation == Orientation.Vertical && direction == Direction.LEFT -> false
+                orientation == Orientation.Vertical && direction == Direction.RIGHT -> false
+                else -> canDrag?.invoke(direction) ?: true
+            }
+        }
+    }
+
+    override fun onInit(customEventDispatcher: CustomEventDispatcher) {
+        scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+    }
+
     override fun onPointerInput(
         changes: List<PointerInputChange>,
         pass: PointerEventPass,
         bounds: IntSize
     ): List<PointerInputChange> {
 
-        if (!passedSlop &&
-            (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown)
-        ) {
-            // Get current average change.
-            val averagePositionChange = getAveragePositionChange(changes)
-            val dx = averagePositionChange.x
-            val dy = averagePositionChange.y
+        scrollOrientationLocker.onPointerInputSetup(changes, pass)
 
-            // Track changes during postUp and during postDown.  This allows for fancy dragging
-            // due to a parent being dragged and will likely be removed.
-            // TODO(b/157087973): Likely remove this two pass complexity.
-            if (pass == PointerEventPass.PostUp) {
-                dxForPass = dx
-                dyForPass = dy
-                dxUnderSlop += dx
-                dyUnderSlop += dy
-            } else {
-                dxUnderSlop += dx - dxForPass
-                dyUnderSlop += dy - dyForPass
+        if (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown) {
+
+            // Filter changes for those that we can interact with due to our orientation.
+            val applicableChanges =
+                with(orientation) {
+                    if (this != null) {
+                        scrollOrientationLocker.getPointersFor(changes, this)
+                    } else {
+                        changes
+                    }
+                }
+
+            if (!passedSlop) {
+
+                // Get current average change.
+                val averagePositionChange = getAveragePositionChange(applicableChanges)
+                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.
+                // TODO(b/157087973): Likely remove this two pass complexity.
+                if (pass == PointerEventPass.PostUp) {
+                    dxForPass = dx
+                    dyForPass = dy
+                    dxUnderSlop += dx
+                    dyUnderSlop += dy
+                } else {
+                    dxUnderSlop += dx - dxForPass
+                    dyUnderSlop += dy - dyForPass
+                }
+
+                // Map the distance to the direction enum for a call to canDrag.
+                val directionX = averagePositionChange.horizontalDirection()
+                val directionY = averagePositionChange.verticalDirection()
+
+                val canDragX = directionX != null && canDrag?.invoke(directionX) ?: true
+                val canDragY = directionY != null && canDrag?.invoke(directionY) ?: true
+
+                val passedSlopX = canDragX && Math.abs(dxUnderSlop) > touchSlop
+                val passedSlopY = canDragY && Math.abs(dyUnderSlop) > touchSlop
+
+                if (passedSlopX || passedSlopY) {
+                    passedSlop = true
+                    onDragSlopExceeded.invoke()
+                } else {
+                    // If we have passed slop in a direction that we can't drag in, we should reset
+                    // our tracking back to zero so that a user doesn't have to later scroll the slop
+                    // + the extra distance they scrolled in the wrong direction.
+                    if (!canDragX &&
+                        ((directionX == Direction.LEFT && dxUnderSlop < 0) ||
+                                (directionX == Direction.RIGHT && dxUnderSlop > 0))
+                    ) {
+                        dxUnderSlop = 0f
+                    }
+                    if (!canDragY &&
+                        ((directionY == Direction.UP && dyUnderSlop < 0) ||
+                                (directionY == Direction.DOWN && dyUnderSlop > 0))
+                    ) {
+                        dyUnderSlop = 0f
+                    }
+                }
             }
 
-            // Map the distance to the direction enum for a call to canDrag.
-            val directionX = averagePositionChange.horizontalDirection()
-            val directionY = averagePositionChange.verticalDirection()
-
-            val canDragX = directionX != null && canDrag?.invoke(directionX) ?: true
-            val canDragY = directionY != null && canDrag?.invoke(directionY) ?: true
-
-            val passedSlopX = canDragX && Math.abs(dxUnderSlop) > touchSlop
-            val passedSlopY = canDragY && Math.abs(dyUnderSlop) > touchSlop
-
-            if (passedSlopX || passedSlopY) {
-                passedSlop = true
-                onDragSlopExceeded.invoke()
-            } else {
-                // If we have passed slop in a direction that we can't drag in, we should reset
-                // our tracking back to zero so that a user doesn't have to later scroll the slop
-                // + the extra distance they scrolled in the wrong direction.
-                if (!canDragX &&
-                    ((directionX == Direction.LEFT && dxUnderSlop < 0) ||
-                            (directionX == Direction.RIGHT && dxUnderSlop > 0))
-                ) {
-                    dxUnderSlop = 0f
-                }
-                if (!canDragY &&
-                    ((directionY == Direction.UP && dyUnderSlop < 0) ||
-                            (directionY == Direction.DOWN && dyUnderSlop > 0))
-                ) {
-                    dyUnderSlop = 0f
-                }
+            if (pass == PointerEventPass.PostDown &&
+                changes.all { it.changedToUpIgnoreConsumed() }
+            ) {
+                // On the final pass, check to see if all pointers have changed to up, and if they
+                // have, reset.
+                reset()
             }
         }
 
-        if (pass == PointerEventPass.PostDown &&
-            changes.all { it.changedToUpIgnoreConsumed() }
-        ) {
-            reset()
-        }
+        scrollOrientationLocker.onPointerInputTearDown(changes, pass)
+
         return changes
     }
 
     override fun onCancel() {
+        scrollOrientationLocker.onCancel()
         reset()
     }
 
+    override fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
+        scrollOrientationLocker.onCustomEvent(customEvent, pass)
+    }
+
     private fun reset() {
         passedSlop = false
         dxForPass = 0f
@@ -148,6 +213,10 @@
  * Get's the average distance change of all pointers as an Offset.
  */
 private fun getAveragePositionChange(changes: List<PointerInputChange>): Offset {
+    if (changes.isEmpty()) {
+        return Offset.Zero
+    }
+
     val sum = changes.fold(Offset.Zero) { sum, change ->
         sum + change.positionChange()
     }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ExperimentalPointerInput.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ExperimentalPointerInput.kt
new file mode 100644
index 0000000..8ca6b32
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ExperimentalPointerInput.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.gesture
+
+@RequiresOptIn("This pointer input API is experimental and is likely to change before becoming " +
+        "stable.")
+annotation class ExperimentalPointerInput
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt
index 8484c3a..08a9cee 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalPointerInput::class)
+
 package androidx.ui.core.gesture
 
 import androidx.compose.remember
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
 import androidx.ui.core.Modifier
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.PointerId
@@ -28,6 +32,8 @@
 import androidx.ui.core.composed
 import androidx.ui.core.consumeDownChange
 import androidx.ui.core.consumePositionChange
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
 import androidx.ui.core.gesture.util.VelocityTracker
 import androidx.ui.core.pointerinput.PointerInputFilter
 import androidx.ui.core.positionChange
@@ -36,6 +42,9 @@
 import androidx.ui.util.fastAny
 import androidx.ui.util.fastForEach
 
+/**
+ * Defines the callbacks associated with dragging.
+ */
 interface DragObserver {
 
     /**
@@ -45,10 +54,11 @@
      * is null or returns true) and the average distance the pointers have moved are not 0 on
      * both the x and y axes.
      *
-     * @param downPosition The pointer input position of the down event.
+     * Only called if the last called if the most recent call among [onStart], [onStop], and
+     * [onCancel] was [onStop] or [onCancel].
      *
-     * @see onDrag
-     * @see onStop
+     * @param downPosition The average position of all pointer positions when they first touched
+     * down.
      */
     fun onStart(downPosition: Offset) {}
 
@@ -74,16 +84,22 @@
      *
      * This is called once all pointers have stopped interacting with this DragGestureDetector.
      *
-     * Only called if the last call between [onStart] and [onStop] was [onStart].
+     * Only called if the last called if the most recent call among [onStart], [onStop], and
+     * [onCancel] was [onStart].
+     *
+     * @param velocity The velocity of the drag in both orientations at the point in time when all
+     * pointers have released the relevant PointerInputFilter. In pixels per second.
      */
     fun onStop(velocity: Offset) {}
 
     /**
      * Override to be notified when the drag has been cancelled.
      *
-     * This is called if [onStart] has ben called and then a cancellation event has occurs
-     * (for example, due to the gesture detector being removed from the tree) before [onStop] is
-     * called.
+     * This is called in response to a cancellation event such as the associated
+     * PointerInputFilter having been removed from the hierarchy.
+     *
+     * Only called if the last called if the most recent call among [onStart], [onStop], and
+     * [onCancel] was [onStart].
      */
     fun onCancel() {}
 }
@@ -115,29 +131,47 @@
  * When multiple pointers are touching the detector, the drag distance is taken as the average of
  * all of the pointers.
  *
+ * Note: Changing the value of [orientation] will reset the gesture filter such that it will not
+ * respond to input until new pointers are detected.
+ *
  * @param dragObserver The callback interface to report all events related to dragging.
  * @param canStartDragging If set, Before dragging is started ([DragObserver.onStart] is called),
  *                         canStartDragging is called to check to see if it is allowed to start.
+ * @param orientation Limits the directions under which dragging can occur to those that are
+ *                    within the provided orientation, locks pointers that are used to drag in
+ *                    the given orientation to that orientation, and ignores pointers that are
+ *                    locked to other orientations.  If no orientation is provided, does none of
+ *                    the above.
  */
 
-// TODO(b/129784010): Consider also allowing onStart, onDrag, and onStop to be set individually (instead of all being
-//  set via DragObserver).
+// TODO(b/129784010): Consider also allowing onStart, onDrag, and onStop to be set individually
+//  (instead of all being set via DragObserver).
 fun Modifier.rawDragGestureFilter(
     dragObserver: DragObserver,
-    canStartDragging: (() -> Boolean)? = null
+    canStartDragging: (() -> Boolean)? = null,
+    orientation: Orientation? = null
 ): Modifier = composed {
     val filter = remember { RawDragGestureFilter() }
     filter.dragObserver = dragObserver
     filter.canStartDragging = canStartDragging
+    filter.orientation = orientation
     PointerInputModifierImpl(filter)
 }
 
 internal class RawDragGestureFilter : PointerInputFilter() {
     private val velocityTrackers: MutableMap<PointerId, VelocityTracker> = mutableMapOf()
     private val downPositions: MutableMap<PointerId, Offset> = mutableMapOf()
+
+    internal lateinit var dragObserver: DragObserver
+    internal var canStartDragging: (() -> Boolean)? = null
+    internal var orientation: Orientation? = null
+
     private var started = false
-    var canStartDragging: (() -> Boolean)? = null
-    lateinit var dragObserver: DragObserver
+    internal lateinit var scrollOrientationLocker: ScrollOrientationLocker
+
+    override fun onInit(customEventDispatcher: CustomEventDispatcher) {
+        scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+    }
 
     override fun onPointerInput(
         changes: List<PointerInputChange>,
@@ -145,162 +179,202 @@
         bounds: IntSize
     ): List<PointerInputChange> {
 
-            var changesToReturn = changes
+        scrollOrientationLocker.onPointerInputSetup(changes, pass)
 
-            if (pass == PointerEventPass.InitialDown) {
+        var changesToReturn = changes
 
-                if (started) {
-                    // If we are have started we want to prevent any descendants from reacting to
-                    // any down change.
-                    changesToReturn = changesToReturn.map {
-                        if (it.changedToDown()) {
-                            it.consumeDownChange()
-                        } else {
-                            it
-                        }
+        if (pass == PointerEventPass.InitialDown) {
+
+            if (started) {
+                // If we are have started we want to prevent any descendants from reacting to
+                // any down change.
+                changesToReturn = changesToReturn.map {
+                    if (it.changedToDown()) {
+                        it.consumeDownChange()
+                    } else {
+                        it
+                    }
+                }
+            }
+        }
+
+        if (pass == PointerEventPass.PostUp) {
+
+            val applicableChanges =
+                with(orientation) {
+                    if (this != null) {
+                        scrollOrientationLocker.getPointersFor(changes, this)
+                    } else {
+                        changes
+                    }
+                }
+
+            // Handle up changes, which includes removing individual pointer VelocityTrackers
+            // and potentially calling onStop().
+            if (changesToReturn.fastAny { it.changedToUpIgnoreConsumed() }) {
+
+                var velocityTracker: VelocityTracker? = null
+
+                changesToReturn.fastForEach {
+                    // This pointer is up (consumed or not), so we should stop tracking
+                    // information about it.  If the pointer is not locked out of our
+                    // orientation, get the velocity tracker because this might be a fling.
+                    if (it.changedToUp() && applicableChanges.contains(it)) {
+                        velocityTracker = velocityTrackers.remove(it.id)
+                    } else if (it.changedToUpIgnoreConsumed()) {
+                        velocityTrackers.remove(it.id)
+                    }
+                    // removing stored down position for the pointer.
+                    if (it.changedToUp()) {
+                        downPositions.remove(it.id)
+                    }
+                }
+
+                if (changesToReturn.all { it.changedToUpIgnoreConsumed() }) {
+                    // All of the pointers are up, so reset and call onStop.  If we have a
+                    // 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: Offset? =
+                            if (velocityTracker != null) {
+                                changesToReturn = changesToReturn.map {
+                                    it.consumeDownChange()
+                                }
+                                velocityTracker!!.calculateVelocity().pixelsPerSecond
+                            } else {
+                                null
+                            }
+                        started = false
+                        dragObserver.onStop(velocity ?: Offset.Zero)
+                        reset()
                     }
                 }
             }
 
-            if (pass == PointerEventPass.PostUp) {
-
-                // Handle up changes, which includes removing individual pointer VelocityTrackers
-                // and potentially calling onStop().
-                if (changesToReturn.fastAny { it.changedToUpIgnoreConsumed() }) {
-
-                    var velocityTracker: VelocityTracker? = null
-
-                    changesToReturn.fastForEach {
-                        // This pointer is up (consumed or not), so we should stop tracking
-                        // information about it.  Get a reference for the velocity tracker in case
-                        // this is the last pointer and thus we are going to fling.
-                        if (it.changedToUp()) {
-                            velocityTracker = velocityTrackers.remove(it.id)
-                        } else if (it.changedToUpIgnoreConsumed()) {
-                            velocityTrackers.remove(it.id)
-                        }
-                        // removing stored down position for the pointer.
-                        if (it.changedToUp()) {
-                            downPositions.remove(it.id)
-                        }
-                    }
-
-                    if (changesToReturn.all { it.changedToUpIgnoreConsumed() }) {
-                        // All of the pointers are up, so reset and call onStop.  If we have a
-                        // 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: Offset? =
-                                if (velocityTracker != null) {
-                                    changesToReturn = changesToReturn.map {
-                                        it.consumeDownChange()
-                                    }
-                                    velocityTracker!!.calculateVelocity().pixelsPerSecond
-                                } else {
-                                    null
-                                }
-                            started = false
-                            dragObserver.onStop(velocity ?: Offset.Zero)
-                        }
+            // For each new pointer that has been added, start tracking information about it.
+            if (changesToReturn.fastAny { it.changedToDownIgnoreConsumed() }) {
+                changesToReturn.fastForEach {
+                    // If a pointer has changed to down, we should start tracking information
+                    // about it.
+                    if (it.changedToDownIgnoreConsumed()) {
+                        velocityTrackers[it.id] = VelocityTracker()
+                            .apply {
+                                addPosition(
+                                    it.current.uptime!!,
+                                    it.current.position!!
+                                )
+                            }
+                        downPositions[it.id] = it.current.position!!
                     }
                 }
+            }
+        }
 
-                // For each new pointer that has been added, start tracking information about it.
-                if (changesToReturn.fastAny { it.changedToDownIgnoreConsumed() }) {
-                    changesToReturn.fastForEach {
-                        // If a pointer has changed to down, we should start tracking information
-                        // about it.
-                        if (it.changedToDownIgnoreConsumed()) {
-                            velocityTrackers[it.id] = VelocityTracker()
-                                .apply {
-                                    addPosition(
-                                        it.current.uptime!!,
-                                        it.current.position!!
-                                    )
-                                }
-                            downPositions[it.id] = it.current.position!!
-                        }
+        // This if block is run for both PostUp and PostDown to allow for the detector to
+        // respond to modified changes after ancestors may have modified them.  (This allows
+        // for things like dragging an ancestor scrolling container, while keeping a pointer on
+        // a descendant scrolling container, and the descendant scrolling container keeping the
+        // descendant still.)
+        if (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown) {
+
+            var (movedChanges, otherChanges) = changesToReturn.partition {
+                it.current.down && !it.changedToDownIgnoreConsumed()
+            }
+
+            movedChanges.fastForEach {
+                // TODO(shepshapard): handle the case that the pointerTrackingData is null,
+                // either with an exception or a logged error, or something else.
+                val velocityTracker = velocityTrackers[it.id]
+
+                if (velocityTracker != null) {
+
+                    // Add information to the velocity tracker only during one pass.
+                    // TODO(shepshapard): VelocityTracker needs to be updated to not accept
+                    // position information, but rather vector information about movement.
+                    if (pass == PointerEventPass.PostUp) {
+                        velocityTracker.addPosition(
+                            it.current.uptime!!,
+                            it.current.position!!
+                        )
                     }
                 }
             }
 
-            // This if block is run for both PostUp and PostDown to allow for the detector to
-            // respond to modified changes after ancestors may have modified them.  (This allows
-            // for things like dragging an ancestor scrolling container, while keeping a pointer on
-            // a descendant scrolling container, and the descendant scrolling container keeping the
-            // descendant still.)
-            if (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown) {
+            // Check to see if we are already started so we don't have to call canStartDragging again.
+            val canStart = !started && canStartDragging?.invoke() ?: true
 
-                var (movedChanges, otherChanges) = changesToReturn.partition {
-                    it.current.down && !it.changedToDownIgnoreConsumed()
-                }
+            // At this point, check to see if we have started, and if we have, we may
+            // be calling onDrag and updating change information on the PointerInputChanges.
+            if (started || canStart) {
+
+                var totalDx = 0f
+                var totalDy = 0f
+
+                val verticalPointers =
+                    scrollOrientationLocker.getPointersFor(
+                        movedChanges,
+                        Orientation.Vertical
+                    )
+                val horizontalPointers =
+                    scrollOrientationLocker.getPointersFor(
+                        movedChanges,
+                        Orientation.Horizontal
+                    )
 
                 movedChanges.fastForEach {
-                    // TODO(shepshapard): handle the case that the pointerTrackingData is null,
-                    // either with an exception or a logged error, or something else.
-                    val velocityTracker = velocityTrackers[it.id]
-
-                    if (velocityTracker != null) {
-
-                        // Add information to the velocity tracker only during one pass.
-                        // TODO(shepshapard): VelocityTracker needs to be updated to not accept
-                        // position information, but rather vector information about movement.
-                        if (pass == PointerEventPass.PostUp) {
-                            velocityTracker.addPosition(
-                                it.current.uptime!!,
-                                it.current.position!!
-                            )
-                        }
-                    }
-                }
-
-                // Check to see if we are already started so we don't have to call canStartDragging again.
-                val canStart = !started && canStartDragging?.invoke() ?: true
-
-                // At this point, check to see if we have started, and if we have, we may
-                // be calling onDrag and updating change information on the PointerInputChanges.
-                if (started || canStart) {
-
-                    var totalDx = 0f
-                    var totalDy = 0f
-
-                    movedChanges.fastForEach {
+                    if (horizontalPointers.contains(it) && orientation !=
+                        Orientation.Vertical
+                    ) {
                         totalDx += it.positionChange().x
+                    }
+                    if (verticalPointers.contains(it) && orientation !=
+                        Orientation.Horizontal
+                    ) {
                         totalDy += it.positionChange().y
                     }
-
-                    if (totalDx != 0f || totalDy != 0f) {
-
-                        // At this point, if we have not started, check to see if we should start
-                        // and if we should, update our state and call onStart().
-                        if (!started && canStart) {
-                            started = true
-                            dragObserver.onStart(downPositions.values.averagePosition())
-                            downPositions.clear()
-                        }
-
-                        if (started) {
-
-                            val consumed = dragObserver.onDrag(
-                                Offset(
-                                    totalDx / changesToReturn.size,
-                                    totalDy / changesToReturn.size
-                                )
-                            )
-
-                            movedChanges = movedChanges.map {
-                                it.consumePositionChange(consumed.x, consumed.y)
-                            }
-                        }
-                    }
                 }
 
-                changesToReturn = movedChanges + otherChanges
+                if (totalDx != 0f || totalDy != 0f) {
+
+                    // At this point, if we have not started, check to see if we should start
+                    // and if we should, update our state and call onStart().
+                    if (!started) {
+                        started = true
+                        dragObserver.onStart(downPositions.values.averagePosition())
+                        downPositions.clear()
+                    }
+
+                    // Only need to do this during the first pass that we care about (PostUp).
+                    if (pass == PointerEventPass.PostUp) {
+                        orientation?.let {
+                            scrollOrientationLocker.attemptToLockPointers(
+                                movedChanges,
+                                it
+                            )
+                        }
+                    }
+
+                    val consumed = dragObserver.onDrag(
+                        Offset(
+                            totalDx / changesToReturn.size,
+                            totalDy / changesToReturn.size
+                        )
+                    )
+
+                    movedChanges = movedChanges.map {
+                        it.consumePositionChange(consumed.x, consumed.y)
+                    }
+                }
             }
 
-            return changesToReturn
+            changesToReturn = movedChanges + otherChanges
         }
 
+        scrollOrientationLocker.onPointerInputTearDown(changes, pass)
+
+        return changesToReturn
+    }
+
     override fun onCancel() {
         downPositions.clear()
         velocityTrackers.clear()
@@ -308,13 +382,24 @@
             started = false
             dragObserver.onCancel()
         }
+        scrollOrientationLocker.onCancel()
+        reset()
+    }
+
+    override fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
+        scrollOrientationLocker.onCustomEvent(customEvent, pass)
+    }
+
+    private fun reset() {
+        downPositions.clear()
+        velocityTrackers.clear()
     }
 }
 
 private fun Iterable<Offset>.averagePosition(): Offset {
     var x = 0f
     var y = 0f
-    forEach {
+    this.forEach {
         x += it.x
         y += it.y
     }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ScrollGestureFilter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ScrollGestureFilter.kt
new file mode 100644
index 0000000..7a7b055
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ScrollGestureFilter.kt
@@ -0,0 +1,197 @@
+/*
+ * 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.core.gesture
+
+import androidx.compose.remember
+import androidx.ui.core.Direction
+import androidx.ui.core.Modifier
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.composed
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
+import androidx.ui.geometry.Offset
+
+/**
+ * Defines the callbacks associated with scrolling.
+ */
+interface ScrollCallback {
+
+    /**
+     * Override to be notified when a scroll has started.
+     *
+     * This will be called as soon as the average distance of all pointers surpasses the touch slop
+     * in the relevant orientation.
+     *
+     * Only called if the last called if the most recent call among [onStart], [onStop], and
+     * [onCancel] was [onStop] or [onCancel].
+     *
+     * @param downPosition The pointer input position of the down event.
+     */
+    fun onStart(downPosition: Offset) {}
+
+    /**
+     * Override to be notified when a distance has been scrolled.
+     *
+     * When overridden, return the amount of the [scrollDistance] that has been consumed.
+     *
+     * Called immediately after [onStart] and for every subsequent pointer movement, as long as the
+     * movement was enough to constitute a scroll (the average movement on in the relevant
+     * orientation  is not equal to 0).
+     *
+     * Note: This may be called multiple times in a single pass and the values should be accumulated
+     * for each call.
+     *
+     * @param scrollDistance The distance that has been scrolled.  Reflects the average scroll
+     * distance of all pointers.
+     */
+    fun onScroll(scrollDistance: Float) = 0f
+
+    /**
+     * Override to be notified when a scroll has stopped.
+     *
+     * This is called once all pointers have released the associated PointerInputFilter.
+     *
+     * Only called if the last called if the most recent call among [onStart], [onStop], and
+     * [onCancel] was [onStart].
+     *
+     * @param velocity The velocity of the scroll in the relevant orientation at the point in time
+     * when all pointers have released the relevant PointerInputFilter. In pixels per second.
+     */
+    fun onStop(velocity: Float) {}
+
+    /**
+     * Override to be notified when the scroll has been cancelled.
+     *
+     * This is called in response to a cancellation event such as the associated
+     * PointerInputFilter having been removed from the hierarchy.
+     *
+     * Only called if the last called if the most recent call among [onStart], [onStop], and
+     * [onCancel] was [onStart].
+     */
+    fun onCancel() {}
+}
+
+/**
+ * Like [Modifier.dragGestureFilter], this gesture filter will detect dragging, but will only do
+ * so along the given [orientation].
+ *
+ * This gesture filter also disambiguates amongst other scrollGestureFilters such that for all
+ * pointers that this gesture filter uses to scroll in the given [orientation], other
+ * scrollGestureFilters (or other clients of [ScrollOrientationLocker]) will not use those same
+ * pointers to drag in the other [orientation].  Likewise, this scrollGestureFilter will not use
+ * pointers to drag if they are already being used to drag in a different orientation.
+ *
+ * Note: [canDrag] will only be queried in directions that exist within the given [orientation].
+ *
+ * Note: Changing the value of [orientation] will reset the gesture filter such that it will not
+ * respond to input until new pointers are detected.
+ *
+ * @param scrollCallback: The set of callbacks for scrolling.
+ * @param orientation: The orientation this gesture filter uses.
+ * @param canDrag Set to limit the types of directions under which touch slop can be exceeded.
+ * Return true if you want a drag to be started due to the touch slop being surpassed in the
+ * given [Direction]. If [canDrag] is not provided, touch slop will be able to be exceeded in all
+ * directions that are in the provided [orientation].
+ * @param startDragImmediately Set to true to have dragging begin immediately when a pointer is
+ * "down", preventing children from responding to the "down" change.  Generally, this parameter
+ * should be set to true when the child of the GestureDetector is animating, such that when a finger
+ * touches it, dragging is immediately started so the animation stops and dragging can occur.
+ */
+// TODO(shepshapard): Consider breaking up ScrollCallback such that the onScroll lambda can be
+//  the final parameter.
+fun Modifier.scrollGestureFilter(
+    scrollCallback: ScrollCallback,
+    orientation: Orientation,
+    canDrag: ((Direction) -> Boolean)? = null,
+    startDragImmediately: Boolean = false
+): Modifier = composed {
+    val coordinator = remember { ScrollGestureFilterCoordinator() }
+    coordinator.scrollCallback = scrollCallback
+    coordinator.orientation = orientation
+
+    // TODO(b/146427920): There is a gap here where RawPressStartGestureDetector can cause a call to
+    //  DragObserver.onStart but if the pointer doesn't move and releases, (or if cancel is called)
+    //  The appropriate callbacks to DragObserver will not be called.
+    rawDragGestureFilter(
+        coordinator.rawDragObserver,
+        coordinator::enabledOrStarted,
+        orientation
+    )
+        .dragSlopExceededGestureFilter(coordinator::enableDrag, canDrag, orientation)
+        .rawPressStartGestureFilter(
+            coordinator::startDrag,
+            startDragImmediately,
+            PointerEventPass.InitialDown
+        )
+}
+
+/**
+ * Coordinates the logic of rawDragGestureFilter, dragSlopExceededGestureFilter, and
+ * rawPressStartGestureFilter.
+ *
+ * Also maps the output of rawDragGestureFilter to the output of scrollGestureFilter.
+ */
+private class ScrollGestureFilterCoordinator {
+    private var started = false
+    private var enabled = false
+
+    lateinit var scrollCallback: ScrollCallback
+    lateinit var orientation: Orientation
+
+    val enabledOrStarted
+        get() = started || enabled
+
+    fun enableDrag() {
+        enabled = true
+    }
+
+    fun startDrag(downPosition: Offset) {
+        started = true
+        scrollCallback.onStart(downPosition)
+    }
+
+    val rawDragObserver: DragObserver =
+        object : DragObserver {
+            override fun onStart(downPosition: Offset) {
+                if (!started) {
+                    scrollCallback.onStart(downPosition)
+                }
+            }
+
+            override fun onDrag(dragDistance: Offset): Offset {
+                return when (orientation) {
+                    Orientation.Horizontal -> Offset(scrollCallback.onScroll(dragDistance.x), 0f)
+                    Orientation.Vertical -> Offset(0f, scrollCallback.onScroll(dragDistance.y))
+                }
+            }
+
+            override fun onStop(velocity: Offset) {
+                started = false
+                enabled = false
+                return when (orientation) {
+                    Orientation.Horizontal -> scrollCallback.onStop(velocity.x)
+                    Orientation.Vertical -> scrollCallback.onStop(velocity.y)
+                }
+            }
+
+            override fun onCancel() {
+                started = false
+                enabled = false
+                scrollCallback.onCancel()
+            }
+        }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLocker.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLocker.kt
new file mode 100644
index 0000000..9f2a102
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLocker.kt
@@ -0,0 +1,230 @@
+/*
+ * 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.gesture.scrollorientationlocking
+
+import androidx.annotation.VisibleForTesting
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerId
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.changedToDownIgnoreConsumed
+import androidx.ui.core.changedToUpIgnoreConsumed
+import androidx.ui.core.gesture.ExperimentalPointerInput
+import androidx.ui.core.pointerinput.PointerInputFilter
+import androidx.ui.util.fastForEach
+
+// TODO(shepshapard): This should be in a more generic place.
+enum class Orientation {
+    Vertical, Horizontal
+}
+
+/**
+ * Manages scroll orientation locking amongst all participating gesture filters.
+ *
+ * Does so by allowing gesture filters to do the following:
+ *
+ * 1. Request that pointers be locked to particular [Orientation]s
+ * 2. Query which pointers from a given set are allowed to be considered for a given orientation.
+ *
+ * A specific contract must also be followed in order to setup and tear down scroll orientation
+ * locking.  Please see [onPointerInputSetup], [onPointerInputTearDown], [onCustomEvent], and
+ * [onCancel] to use
+ * this correctly.
+ */
+@ExperimentalPointerInput
+class ScrollOrientationLocker(private val customEventDispatcher: CustomEventDispatcher) {
+
+    private var locker: InternalScrollOrientationLocker? = null
+    private var lockerOwner = false
+
+    /**
+     * Handles the initialization of scroll orientation locking management, including internally
+     * managed distribution of shared state.
+     *
+     * For proper initialization to work, [onCustomEvent] must also be called in
+     * [PointerInputFilter.onCustomEvent].
+     *
+     * This method should simply be called toward the top of [PointerInputFilter.onPointerInput]
+     * for all [PointerEventPass]es, before [attemptToLockPointers] or [getPointersFor] are called.
+     *
+     * @see onPointerInputTearDown
+     * @see onCancel
+     * @see onCustomEvent
+     */
+    fun onPointerInputSetup(changes: List<PointerInputChange>, pass: PointerEventPass) {
+        if (pass != PointerEventPass.InitialDown) {
+            return
+        }
+
+        if (locker == null && changes.all { it.changedToDownIgnoreConsumed() }) {
+            lockerOwner = true
+            locker = InternalScrollOrientationLocker().also {
+                customEventDispatcher.dispatchCustomEvent(
+                    ShareScrollOrientationLockerEvent(it)
+                )
+            }
+        } else if (lockerOwner && changes.any { it.changedToDownIgnoreConsumed() }) {
+            // TODO(shepshapard): This is always doing some extra work given that some of the
+            //  child gesture filters may already have received the InternalScrollOrientationLocker.
+            //  It is functionality correct, but could be optimized (though it would likely
+            //  not provide that much of a performance boost in the real world.
+            customEventDispatcher.dispatchCustomEvent(
+                ShareScrollOrientationLockerEvent(locker!!)
+            )
+        }
+    }
+
+    /**
+     * Handles the tear down of internal state.
+     *
+     * This method must be called toward the bottom of [PointerInputFilter.onPointerInput]
+     * for all [PointerEventPass]es, and [attemptToLockPointers] or [getPointersFor] should not
+     * be called afterwards.
+     *
+     * @see onPointerInputSetup
+     * @see onCancel
+     * @see onCustomEvent
+     */
+    fun onPointerInputTearDown(changes: List<PointerInputChange>, pass: PointerEventPass) {
+        if (pass == PointerEventPass.PostDown && changes.all { it.changedToUpIgnoreConsumed() }) {
+            reset()
+        }
+    }
+
+    /**
+     * Handles the tear down of internal state due to a call to [PointerInputFilter.onCancel].
+     *
+     * Must be called in [PointerInputFilter.onCancel].
+     *
+     * @see onPointerInputSetup
+     * @see onPointerInputTearDown
+     * @see onCustomEvent
+     */
+    fun onCancel() {
+        reset()
+    }
+
+    /**
+     * Handles the other half of [onPointerInputSetup] and must be called in all calls to
+     * [PointerInputFilter.onCustomEvent].
+     *
+     * @see onPointerInputSetup
+     * @see onPointerInputTearDown
+     * @see onCancel
+     * @throws [IllegalStateException] if this [ScrollOrientationLocker] receives a
+     * [ShareScrollOrientationLockerEvent] via this method after having already dispatched a
+     * [ShareScrollOrientationLockerEvent] itself.
+     */
+    fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
+
+        if (pass == PointerEventPass.InitialDown &&
+            customEvent is ShareScrollOrientationLockerEvent) {
+            if (lockerOwner) {
+                throw IllegalStateException("This instance of ScrollOrientationLocker should " +
+                        "never receive a ShareScrollOrientationLockerEvent because it already " +
+                        "dispatched one, and thus should be the only one in it's subtree to " +
+                        "dispatch one.")
+            }
+            locker = customEvent.scrollOrientationLocker
+        }
+    }
+
+    /**
+     * Locks the [PointerId]s associated with the [changes] to [orientation].
+     *
+     * This effects which [changes] are returned by [getPointersFor].
+     *
+     * Pointers that are already locked to a given orientation cannot be later locked to a different
+     * orientation.
+     *
+     * @throws [IllegalStateException] if this method is called when this
+     * [ScrollOrientationLocker] has not yet been initialized.  This is likely happening because
+     * [onPointerInputSetup] is not being called with every [PointerEventPass] before this method
+     * is being called.
+     */
+    fun attemptToLockPointers(changes: List<PointerInputChange>, orientation: Orientation) {
+        if (locker == null) {
+            throw IllegalStateException("Internal state has not been set.  This method should not" +
+                    " be called in any place but after calls to onPointerInputSetup and before " +
+                    "calls to onPointerInputTearDown or onCancel. Also, onCustomEvent must be " +
+                    "called appropriately.  See docs for details.")
+        }
+        locker!!.attemptToLockPointers(changes, orientation)
+    }
+
+    /**
+     * Filters the [changes] for those that are allowed to be acted upon for the [orientation].
+     *
+     * A change can be acted on if it was not already locked in the other orientation.
+     *
+     * For example, if pointer 1 was previously locked to Horizontal via [attemptToLockPointers]
+     * then calling this method with pointers 1 and 2 and the following orientation will result
+     * in the following pointers being returned:
+     *
+     * - Orientation.Horizontal -> (1, 2)
+     * - Orientation.Vertical -> (2)
+     *
+     * @throws [IllegalStateException] if this method is called when this
+     * [ScrollOrientationLocker] has not yet been initialized.  This is likely happening because
+     * [onPointerInputSetup] is not being called with every [PointerEventPass] before this method
+     * is being called.
+     */
+    fun getPointersFor(
+        changes: List<PointerInputChange>,
+        orientation: Orientation
+    ): List<PointerInputChange> {
+        if (locker == null) {
+            throw IllegalStateException("Internal state has not been set.  This method should not" +
+                    " be called in any place but after calls to onPointerInputSetup and before " +
+                    "calls to onPointerInputTearDown or onCancel. Also, onCustomEvent must be " +
+                    "called appropriately.  See docs for details.")
+        }
+        return locker!!.getPointersFor(changes, orientation)
+    }
+
+    private fun reset() {
+        locker = null
+        lockerOwner = false
+    }
+}
+
+@VisibleForTesting
+internal class InternalScrollOrientationLocker {
+    private val pointerLocks: MutableMap<PointerId, Orientation> = mutableMapOf()
+
+    fun attemptToLockPointers(pointerIds: List<PointerInputChange>, orientation: Orientation) {
+        pointerIds.fastForEach {
+            if (pointerLocks[it.id] == null) {
+                pointerLocks[it.id] = orientation
+            }
+        }
+    }
+
+    fun getPointersFor(
+        pointerIds: List<PointerInputChange>,
+        orientation: Orientation
+    ): List<PointerInputChange> {
+        return pointerIds
+            .filter { pointerLocks[it.id] == null || pointerLocks[it.id] == orientation }
+    }
+}
+
+@VisibleForTesting
+internal class ShareScrollOrientationLockerEvent(
+    val scrollOrientationLocker: InternalScrollOrientationLocker
+) : CustomEvent
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt
index 785acc9..ec1898b 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt
@@ -20,27 +20,15 @@
 import androidx.compose.Providers
 import androidx.compose.remember
 import androidx.compose.state
-import androidx.ui.core.Alignment
 import androidx.ui.core.ClipboardManagerAmbient
-import androidx.ui.core.Constraints
 import androidx.ui.core.HapticFeedBackAmbient
-import androidx.ui.core.Layout
 import androidx.ui.core.Modifier
-import androidx.ui.core.Placeable
-import androidx.ui.core.Popup
 import androidx.ui.core.TextToolbarAmbient
-import androidx.ui.core.enforce
 import androidx.ui.core.gesture.dragGestureFilter
 import androidx.ui.core.gesture.longPressDragGestureFilter
 import androidx.ui.core.gesture.tapGestureFilter
-import androidx.ui.core.hasFixedHeight
-import androidx.ui.core.hasFixedWidth
 import androidx.ui.core.onPositioned
-import androidx.ui.unit.Dp
-import androidx.ui.unit.IntOffset
-import androidx.ui.unit.IntSize
-import kotlin.math.max
-import kotlin.math.roundToInt
+import androidx.ui.text.InternalTextApi
 
 /**
  * Default SelectionContainer to be used in order to make composables selectable by default.
@@ -61,6 +49,7 @@
  * The selection composable wraps composables and let them to be selectable. It paints the selection
  * area with start and end handles.
  */
+@OptIn(InternalTextApi::class)
 @Composable
 fun SelectionContainer(
     /** Current Selection status.*/
@@ -92,131 +81,33 @@
     Providers(SelectionRegistrarAmbient provides registrarImpl) {
         // Get the layout coordinates of the selection container. This is for hit test of
         // cross-composable selection.
-        Wrap(modifier) {
+        SelectionLayout(modifier) {
             children()
-            for (isStartHandle in listOf(true, false)) {
-                Handle(manager, isStartHandle) {
-                    SelectionHandle(
-                        Modifier.dragGestureFilter(manager.handleDragObserver(isStartHandle)),
-                        manager.selection,
-                        isStartHandle)
+            manager.selection?.let {
+                for (isStartHandle in listOf(true, false)) {
+                    SelectionHandleLayout(
+                        startHandlePosition = manager.startHandlePosition,
+                        endHandlePosition = manager.endHandlePosition,
+                        isStartHandle = isStartHandle,
+                        directions = Pair(it.start.direction, it.end.direction),
+                        handlesCrossed = it.handlesCrossed
+                    ) {
+                        SelectionHandle(
+                            modifier =
+                            Modifier.dragGestureFilter(manager.handleDragObserver(isStartHandle)),
+                            isStartHandle = isStartHandle,
+                            directions = Pair(it.start.direction, it.end.direction),
+                            handlesCrossed = it.handlesCrossed
+                        )
+                    }
                 }
+                SelectionFloatingToolBar(manager = manager)
             }
-            SelectionFloatingToolBar(manager = manager, selection = selection)
         }
     }
 }
 
 @Composable
-private fun SelectionFloatingToolBar(manager: SelectionManager, selection: Selection?) {
-    if (selection == null) return
+private fun SelectionFloatingToolBar(manager: SelectionManager) {
     manager.showSelectionToolbar()
 }
-
-@Composable
-private fun Handle(
-    manager: SelectionManager,
-    isStartHandle: Boolean,
-    handle: @Composable () -> Unit
-) {
-    val offset = if (isStartHandle) manager.startHandlePosition else manager.endHandlePosition
-    val selection = manager.selection
-    if (offset == null || selection == null) {
-        return
-    }
-
-    Wrap {
-        val left = isLeft(isStartHandle, selection)
-        val alignment = if (left) Alignment.TopEnd else Alignment.TopStart
-
-        Popup(
-            alignment = alignment,
-            offset = IntOffset(offset.x.roundToInt(), offset.y.roundToInt()),
-            children = handle
-        )
-    }
-}
-
-/**
- * Selection is transparent in terms of measurement and layout and passes the same constraints to
- * the children.
- */
-@Composable
-private fun Wrap(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
-    Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
-        val placeables = measurables.map { measurable ->
-            measurable.measure(constraints)
-        }
-
-        val width = placeables.fold(0) { maxWidth, placeable ->
-            max(maxWidth, (placeable.width))
-        }
-
-        val height = placeables.fold(0) { minWidth, placeable ->
-            max(minWidth, (placeable.height))
-        }
-
-        layout(width, height) {
-            placeables.forEach { placeable ->
-                placeable.placeAbsolute(0, 0)
-            }
-        }
-    }
-}
-
-/**
- * A Container Box implementation used for selection children and handle layout
- */
-@Composable
-internal fun SimpleContainer(
-    modifier: Modifier = Modifier,
-    width: Dp? = null,
-    height: Dp? = null,
-    children: @Composable () -> Unit
-) {
-    Layout(children, modifier) { measurables, incomingConstraints, _ ->
-        val containerConstraints = Constraints()
-            .copy(
-                width?.toIntPx() ?: 0,
-                width?.toIntPx() ?: Constraints.Infinity,
-                height?.toIntPx() ?: 0,
-                height?.toIntPx() ?: Constraints.Infinity
-            )
-            .enforce(incomingConstraints)
-        val childConstraints = containerConstraints.copy(minWidth = 0, minHeight = 0)
-        var placeable: Placeable? = null
-        val containerWidth = if (
-            containerConstraints.hasFixedWidth
-        ) {
-            containerConstraints.maxWidth
-        } else {
-            placeable = measurables.firstOrNull()?.measure(childConstraints)
-            max((placeable?.width ?: 0), containerConstraints.minWidth)
-        }
-        val containerHeight = if (
-            containerConstraints.hasFixedHeight
-        ) {
-            containerConstraints.maxHeight
-        } else {
-            if (placeable == null) {
-                placeable = measurables.firstOrNull()?.measure(childConstraints)
-            }
-            max((placeable?.height ?: 0), containerConstraints.minHeight)
-        }
-        layout(containerWidth, containerHeight) {
-            val p = placeable ?: measurables.firstOrNull()?.measure(childConstraints)
-            p?.let {
-                val position = Alignment.Center.align(
-                    IntSize(
-                        containerWidth - it.width,
-                        containerHeight - it.height
-                    )
-                )
-                it.place(
-                    position.x,
-                    position.y
-                )
-            }
-        }
-    }
-}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt
index 3cd7593..1bc3d9a 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt
@@ -26,6 +26,7 @@
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.Path
 import androidx.ui.graphics.drawscope.DrawScope
+import androidx.ui.text.InternalTextApi
 import androidx.ui.text.style.TextDirection
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
@@ -115,19 +116,20 @@
     }
 }
 
+/**
+ * @suppress
+ */
+@InternalTextApi
 @Composable
-internal fun SelectionHandle(
+fun SelectionHandle(
     modifier: Modifier,
-    selection: Selection?,
-    isStartHandle: Boolean
+    isStartHandle: Boolean,
+    directions: Pair<TextDirection, TextDirection>,
+    handlesCrossed: Boolean
 ) {
-    if (selection == null) {
-        return
-    }
-
     SelectionHandleLayout(
         modifier,
-        isLeft(isStartHandle, selection))
+        isLeft(isStartHandle, directions, handlesCrossed))
 }
 
 /**
@@ -135,12 +137,13 @@
  */
 internal fun isLeft(
     isStartHandle: Boolean,
-    selection: Selection
+    directions: Pair<TextDirection, TextDirection>,
+    handlesCrossed: Boolean
 ): Boolean {
     if (isStartHandle) {
-        return isHandleLtrDirection(selection.start.direction, selection.handlesCrossed)
+        return isHandleLtrDirection(directions.first, handlesCrossed)
     } else {
-        return !isHandleLtrDirection(selection.end.direction, selection.handlesCrossed)
+        return !isHandleLtrDirection(directions.second, handlesCrossed)
     }
 }
 
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionLayout.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionLayout.kt
new file mode 100644
index 0000000..69b9aad
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionLayout.kt
@@ -0,0 +1,153 @@
+/*
+ * 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.selection
+
+import androidx.compose.Composable
+import androidx.ui.core.Alignment
+import androidx.ui.core.Constraints
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.core.Placeable
+import androidx.ui.core.Popup
+import androidx.ui.core.enforce
+import androidx.ui.core.hasFixedHeight
+import androidx.ui.core.hasFixedWidth
+import androidx.ui.geometry.Offset
+import androidx.ui.text.InternalTextApi
+import androidx.ui.text.style.TextDirection
+import androidx.ui.unit.Dp
+import androidx.ui.unit.IntOffset
+import androidx.ui.unit.IntSize
+import kotlin.math.max
+import kotlin.math.roundToInt
+
+/**
+ * @suppress
+ */
+@InternalTextApi
+@Composable
+fun SelectionHandleLayout(
+    startHandlePosition: Offset?,
+    endHandlePosition: Offset?,
+    isStartHandle: Boolean,
+    directions: Pair<TextDirection, TextDirection>,
+    handlesCrossed: Boolean,
+    handle: @Composable () -> Unit
+) {
+    val offset = (if (isStartHandle) startHandlePosition else endHandlePosition) ?: return
+
+    SelectionLayout {
+        val left = isLeft(
+            isStartHandle = isStartHandle,
+            directions = directions,
+            handlesCrossed = handlesCrossed
+        )
+        val alignment = if (left) Alignment.TopEnd else Alignment.TopStart
+
+        Popup(
+            alignment = alignment,
+            offset = IntOffset(offset.x.roundToInt(), offset.y.roundToInt()),
+            children = handle
+        )
+    }
+}
+
+/**
+ * Selection is transparent in terms of measurement and layout and passes the same constraints to
+ * the children.
+ * @suppress
+ */
+@InternalTextApi
+@Composable
+fun SelectionLayout(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
+    Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
+        val placeables = measurables.map { measurable ->
+            measurable.measure(constraints)
+        }
+
+        val width = placeables.fold(0) { maxWidth, placeable ->
+            max(maxWidth, (placeable.width))
+        }
+
+        val height = placeables.fold(0) { minWidth, placeable ->
+            max(minWidth, (placeable.height))
+        }
+
+        layout(width, height) {
+            placeables.forEach { placeable ->
+                placeable.placeAbsolute(0, 0)
+            }
+        }
+    }
+}
+
+/**
+ * A Container Box implementation used for selection children and handle layout
+ */
+@Composable
+internal fun SimpleContainer(
+    modifier: Modifier = Modifier,
+    width: Dp? = null,
+    height: Dp? = null,
+    children: @Composable () -> Unit
+) {
+    Layout(children, modifier) { measurables, incomingConstraints, _ ->
+        val containerConstraints = Constraints()
+            .copy(
+                width?.toIntPx() ?: 0,
+                width?.toIntPx() ?: Constraints.Infinity,
+                height?.toIntPx() ?: 0,
+                height?.toIntPx() ?: Constraints.Infinity
+            )
+            .enforce(incomingConstraints)
+        val childConstraints = containerConstraints.copy(minWidth = 0, minHeight = 0)
+        var placeable: Placeable? = null
+        val containerWidth = if (
+            containerConstraints.hasFixedWidth
+        ) {
+            containerConstraints.maxWidth
+        } else {
+            placeable = measurables.firstOrNull()?.measure(childConstraints)
+            max((placeable?.width ?: 0), containerConstraints.minWidth)
+        }
+        val containerHeight = if (
+            containerConstraints.hasFixedHeight
+        ) {
+            containerConstraints.maxHeight
+        } else {
+            if (placeable == null) {
+                placeable = measurables.firstOrNull()?.measure(childConstraints)
+            }
+            max((placeable?.height ?: 0), containerConstraints.minHeight)
+        }
+        layout(containerWidth, containerHeight) {
+            val p = placeable ?: measurables.firstOrNull()?.measure(childConstraints)
+            p?.let {
+                val position = Alignment.Center.align(
+                    IntSize(
+                        containerWidth - it.width,
+                        containerHeight - it.height
+                    )
+                )
+                it.place(
+                    position.x,
+                    position.y
+                )
+            }
+        }
+    }
+}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
index cc8d000..00e458f 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
@@ -32,13 +32,6 @@
     val id: Int
 
     /**
-     * If true, then the semantics modifier applies to the first layout node below it in the tree,
-     * not the composable the modifier is applied to.  This is for use by legacy non-modifier-style
-     * semantics and is planned to be removed (with the behavior 'false' made universal).
-     */
-    val applyToChildLayoutNode: Boolean
-
-    /**
      * The SemanticsConfiguration holds substantive data, especially a list of key/value pairs
      * such as (label -> "buttonName").
      */
@@ -47,7 +40,6 @@
 
 internal class SemanticsModifierCore(
     override val id: Int,
-    override val applyToChildLayoutNode: Boolean,
     mergeAllDescendants: Boolean,
     properties: (SemanticsPropertyReceiver.() -> Unit)?
 ) : SemanticsModifier {
@@ -62,20 +54,15 @@
 /**
  * Add semantics key/value for use in testing, accessibility, and similar use cases.
  *
- * @param applyToChildLayoutNode If true, then the semantics modifier applies to the first layout
- * node below it in the tree, not the composable the modifier is applied to.  This is for use by
- * legacy non-modifier-style semantics and is planned to be removed (with the behavior 'false'
- * made universal).
  * @param mergeAllDescendants Whether the semantic information provided by the owning component and
  * all of its descendants should be treated as one logical entity.
  * @param properties properties to add to the semantics. [SemanticsPropertyReceiver] will be
  * provided in the scope to allow access for common properties and its values.
  */
 fun Modifier.semantics(
-    applyToChildLayoutNode: Boolean = false,
     mergeAllDescendants: Boolean = false,
     properties: (SemanticsPropertyReceiver.() -> Unit)? = null
 ): Modifier = composed {
     val id = remember { SemanticsNode.generateNewId() }
-    SemanticsModifierCore(id, applyToChildLayoutNode, mergeAllDescendants, properties)
+    SemanticsModifierCore(id, mergeAllDescendants, properties)
 }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
index bc8e948..09b6fbe 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
@@ -16,6 +16,7 @@
 
 package androidx.ui.core.semantics
 
+import androidx.ui.core.AlignmentLine
 import androidx.ui.core.LayoutNode
 import androidx.ui.core.LayoutNodeWrapper
 import androidx.ui.core.boundsInRoot
@@ -82,36 +83,31 @@
      * Each semantic node has a unique identifier that is assigned when the node
      * is created.
      */
-    internal constructor(unmergedConfig: SemanticsConfiguration, componentNode: LayoutNode) :
-            this(generateNewId(), unmergedConfig, componentNode)
+    internal constructor(unmergedConfig: SemanticsConfiguration, layoutNode: LayoutNode) :
+            this(generateNewId(), unmergedConfig, layoutNode)
 
     // GEOMETRY
 
     /** The size of the bounding box for this node */
     val size: IntSize
         get() {
-            return layoutNode.coordinates.size
+            return componentNode.coordinates.size
         }
 
     /** The bounding box for this node relative to the root of this Compose hierarchy */
     val boundsInRoot: PxBounds
         get() {
-            return layoutNode.coordinates.boundsInRoot
+            return componentNode.coordinates.boundsInRoot
         }
 
     val globalBounds: PxBounds
         get() {
-            return layoutNode.coordinates.globalBounds
+            return componentNode.coordinates.globalBounds
         }
 
     val globalPosition: Offset
         get() {
-            return layoutNode.coordinates.globalPosition
-        }
-
-    private val layoutNode: LayoutNode
-        get() {
-            return componentNode.requireLayoutNodeAppliedTo()
+            return componentNode.coordinates.globalPosition
         }
 
     /**
@@ -124,6 +120,14 @@
             return buildMergedConfig()
         }
 
+    /**
+     * Returns the position of an [alignment line][AlignmentLine], or [AlignmentLine.Unspecified]
+     * if the line is not provided.
+     */
+    fun getAlignmentLinePosition(line: AlignmentLine): Int {
+        return componentNode.coordinates[line]
+    }
+
     private fun buildMergedConfig(
         parentNode: SemanticsNode? = null,
         mergedConfigFromParent: SemanticsConfiguration? = null,
@@ -174,12 +178,7 @@
     private fun unmergedChildren(): List<SemanticsNode> {
         val unmergedChildren: MutableList<SemanticsNode> = mutableListOf()
 
-        var searchRoot: LayoutNode? = componentNode
-        if (searchRoot?.outerSemantics?.semanticsModifier?.applyToChildLayoutNode == true) {
-            searchRoot = componentNode.findLastConsecutiveSemanticsNode()
-        }
-        val semanticsChildren =
-            searchRoot?.findOneLayerOfSemanticsWrappers() ?: emptyList()
+        val semanticsChildren = componentNode.findOneLayerOfSemanticsWrappers()
         semanticsChildren.fastForEach { semanticsChild ->
             unmergedChildren.add(semanticsChild.semanticsNode())
         }
@@ -243,23 +242,7 @@
     // TODO(b/145947383): this needs to be the *merged* parent
     val parent: SemanticsNode?
         get() {
-            // This searches up the layout tree and takes into account
-            // collapsing of adjacent SemanticsWrappers into a single
-            // SemanticsNode.
-            // Example: if L are normal layout node and S are semantics nodes,
-            // and the ComponentNode tree is a simple list-like tree
-            // "<ROOT>, S, S, L, S, S, S, L, L, S"
-            //          ^        ^              ^
-            //          a        b              c
-            // then 'c'.parent == 'b', and 'b'.parent == 'a'
-
-            // (This complexity is temporary -- semantics collapsing will be
-            // replaced by modifier chains soon.)
-
-            var node = componentNode
-                .findClosestParentNode { it.outerSemantics != null }
-                ?.findHighestConsecutiveAncestor {
-                    it.outerSemantics?.semanticsModifier?.applyToChildLayoutNode == true }
+            var node = componentNode.findClosestParentNode { it.outerSemantics != null }
 
             return node?.outerSemantics?.semanticsNode()
         }
@@ -292,21 +275,6 @@
     }
 
 /**
- * Returns the highest in a consecutive chain of this + this's parents all meeting the predicate.
-*/
-private fun LayoutNode.findHighestConsecutiveAncestor(
-    selector: (LayoutNode) -> Boolean
-): LayoutNode? {
-    var prev = this
-    var currentParent = parent
-    while (currentParent != null && selector(currentParent)) {
-        prev = currentParent
-        currentParent = currentParent.parent
-    }
-    return prev
-}
-
-/**
  * Executes [selector] on every parent of this [SemanticsNode] and returns the closest
  * [SemanticsNode] to return `true` from [selector] or null if [selector] returns false
  * for all ancestors.
@@ -334,11 +302,11 @@
 }
 
 private fun LayoutNode.findOneLayerOfSemanticsWrappers(): List<SemanticsWrapper> {
-    val childSemanticsComponentNodes = mutableListOf<SemanticsWrapper>()
+    val childSemanticsLayoutNodes = mutableListOf<SemanticsWrapper>()
     children.fastForEach { child ->
-        findOneLayerOfSemanticsWrappersRecursive(childSemanticsComponentNodes, child)
+        findOneLayerOfSemanticsWrappersRecursive(childSemanticsLayoutNodes, child)
     }
-    return childSemanticsComponentNodes
+    return childSemanticsLayoutNodes
 }
 
 private fun LayoutNode.findOneLayerOfSemanticsWrappersRecursive(
@@ -354,35 +322,3 @@
         }
     }
 }
-
-private fun LayoutNode.findLastConsecutiveSemanticsNode(): LayoutNode? {
-    children.fastForEach { child ->
-        if (child.outerSemantics != null) {
-            if (child.outerSemantics?.semanticsModifier?.applyToChildLayoutNode == false)
-                return child
-            return child.findLastConsecutiveSemanticsNode()
-        } // else, keep looking through the other children
-    }
-
-    return this
-}
-
-private fun LayoutNode.findLayoutNodeAppliedTo(): LayoutNode? {
-    if ((outerSemantics == null ||
-            outerSemantics?.semanticsModifier?.applyToChildLayoutNode == false)) {
-        return this
-    }
-    children.fastForEach { child ->
-            val layoutChild = child.findLayoutNodeAppliedTo()
-            if (layoutChild != null) {
-                return layoutChild
-            }
-    }
-
-    return null
-}
-
-private fun LayoutNode.requireLayoutNodeAppliedTo(): LayoutNode {
-    return findLayoutNodeAppliedTo()
-        ?: throw IllegalStateException("This component has no layout children")
-}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
index 083cfc4..2069190 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
@@ -18,7 +18,6 @@
 
 import androidx.ui.core.DelegatingLayoutNodeWrapper
 import androidx.ui.core.LayoutNodeWrapper
-import androidx.ui.util.fastForEach
 
 internal class SemanticsWrapper(
     wrapped: LayoutNodeWrapper,
@@ -32,49 +31,25 @@
 
     fun collapsedSemanticsConfiguration(): SemanticsConfiguration {
         var config = SemanticsConfiguration()
-        collapseChainedSemanticsIntoTopConfig(config, this)
+        config.absorb(modifier.semanticsConfiguration, ignoreAlreadySet = true)
+
+        val innerConfig = wrapped.nearestSemantics?.collapsedSemanticsConfiguration()
+        if (innerConfig != null) {
+            config.absorb(innerConfig, ignoreAlreadySet = true)
+        }
         return config
     }
 
+    override fun detach() {
+        super.detach()
+        layoutNode.owner?.onSemanticsChange()
+    }
+
+    override fun onModifierChanged() {
+        layoutNode.owner?.onSemanticsChange()
+    }
+
     override fun toString(): String {
         return "${super.toString()} localConfig: ${modifier.semanticsConfiguration}"
     }
-
-    /**
-     * "Collapses" together the [SemanticsConfiguration]s that will apply to the child [LayoutNode].
-     *
-     * This ignores semantic boundaries (because they only apply once the node
-     * is built), and currently does not validate that a [LayoutNode] actually
-     * exists as a child (though this is not contractual)
-     */
-    private fun collapseChainedSemanticsIntoTopConfig(
-        parentConfig: SemanticsConfiguration,
-        topNodeOfConfig: SemanticsWrapper
-    ) {
-        parentConfig.absorb(modifier.semanticsConfiguration, ignoreAlreadySet = true)
-
-        if (semanticsModifier.applyToChildLayoutNode) {
-            // Recursively collapse the chain, if we have an immediate child
-            findOneImmediateChild()?.collapseChainedSemanticsIntoTopConfig(
-                parentConfig, topNodeOfConfig)
-        } else {
-            // Collapse locally within the modifiers directly applying to the current layout node
-            val innerConfig = wrapped.nearestSemantics?.collapsedSemanticsConfiguration()
-            if (innerConfig != null) {
-                parentConfig.absorb(innerConfig, ignoreAlreadySet = true)
-            }
-        }
-    }
-
-    // This searches the children down only one level of the tree and returns one child found.
-    // Note that this assumes each LayoutNode only has one semantics modifier for now.
-    private fun findOneImmediateChild(): SemanticsWrapper? {
-        var immediateChild: SemanticsWrapper? = null
-        layoutNode.children.fastForEach { child ->
-            if (child.outerSemantics != null) {
-                immediateChild = child.outerSemantics
-            }
-        }
-        return immediateChild
-    }
 }
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt
index 85db0b7..a42aac7 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt
@@ -16,25 +16,21 @@
 @file:OptIn(ExperimentalComposeApi::class)
 package androidx.ui.graphics.vector
 
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
+import androidx.compose.AbstractApplier
 import androidx.compose.Composable
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
 import androidx.compose.CompositionReference
 import androidx.compose.Composition
 import androidx.compose.ExperimentalComposeApi
-import androidx.compose.ComposeCompilerApi
 import androidx.compose.Recomposer
-import androidx.compose.SlotTable
 import androidx.compose.compositionFor
-import androidx.compose.currentComposer
+import androidx.compose.emit
+import androidx.compose.key
 import androidx.ui.graphics.Brush
 import androidx.ui.graphics.StrokeCap
 import androidx.ui.graphics.StrokeJoin
 
 @Composable
-fun VectorScope.Group(
+fun Group(
     name: String = DefaultGroupName,
     rotation: Float = DefaultRotation,
     pivotX: Float = DefaultPivotX,
@@ -44,25 +40,29 @@
     translationX: Float = DefaultTranslationX,
     translationY: Float = DefaultTranslationY,
     clipPathData: List<PathNode> = EmptyPath,
-    children: @Composable VectorScope.() -> Unit
+    children: @Composable () -> Unit
 ) {
-    GroupComponent(
-        name = name,
-        rotation = rotation,
-        pivotX = pivotX,
-        pivotY = pivotY,
-        scaleX = scaleX,
-        scaleY = scaleY,
-        translationX = translationX,
-        translationY = translationY,
-        clipPathData = clipPathData
-    ) {
-        children()
+    key(name) {
+        emit<GroupComponent, VectorApplier>(
+            ctor = { GroupComponent(name) },
+            update = {
+                set(rotation) { this.rotation = it }
+                set(pivotX) { this.pivotX = it }
+                set(pivotY) { this.pivotY = it }
+                set(scaleX) { this.scaleX = it }
+                set(scaleY) { this.scaleY = it }
+                set(translationX) { this.translationX = it }
+                set(translationY) { this.translationY = it }
+                set(clipPathData) { this.clipPathData = it }
+            }
+        ) {
+            children()
+        }
     }
 }
 
 @Composable
-fun VectorScope.Path(
+fun Path(
     pathData: List<PathNode>,
     name: String = DefaultPathName,
     fill: Brush? = null,
@@ -74,119 +74,58 @@
     strokeLineJoin: StrokeJoin = DefaultStrokeLineJoin,
     strokeLineMiter: Float = DefaultStrokeLineMiter
 ) {
-    PathComponent(
-        name = name,
-        pathData = pathData,
-        fill = fill,
-        fillAlpha = fillAlpha,
-        stroke = stroke,
-        strokeAlpha = strokeAlpha,
-        strokeLineWidth = strokeLineWidth,
-        strokeLineJoin = strokeLineJoin,
-        strokeLineCap = strokeLineCap,
-        strokeLineMiter = strokeLineMiter
-    )
+    key(name) {
+        emit<PathComponent, VectorApplier>(
+            ctor = { PathComponent(name) },
+            update = {
+                set(pathData) { this.pathData = it }
+                set(fill) { this.fill = it }
+                set(fillAlpha) { this.fillAlpha = it }
+                set(stroke) { this.stroke = it }
+                set(strokeAlpha) { this.strokeAlpha = it }
+                set(strokeLineWidth) { this.strokeLineWidth = it }
+                set(strokeLineJoin) { this.strokeLineJoin = it }
+                set(strokeLineCap) { this.strokeLineCap = it }
+                set(strokeLineMiter) { this.strokeLineMiter = it }
+            }
+        )
+    }
 }
 
-class VectorScope internal constructor (internal val composer: VectorComposer)
-
 @Suppress("NAME_SHADOWING")
 internal fun composeVector(
     container: VectorComponent,
     recomposer: Recomposer,
     parent: CompositionReference? = null,
-    composable: @Composable VectorScope.(viewportWidth: Float, viewportHeight: Float) -> Unit
+    composable: @Composable (viewportWidth: Float, viewportHeight: Float) -> Unit
 ): Composition = compositionFor(
-    container = container,
-    recomposer = recomposer,
-    parent = parent,
-    composerFactory = { slots, recomposer -> VectorComposer(container.root, slots, recomposer) }
+    container,
+    VectorApplier(container.root),
+    recomposer,
+    parent
 ).apply {
     setContent {
-        val composer = currentComposer as VectorComposer
-        val scope = VectorScope(composer)
-        scope.composable(container.viewportWidth, container.viewportHeight)
+        composable(container.viewportWidth, container.viewportHeight)
     }
 }
 
-@OptIn(ComposeCompilerApi::class)
-internal class VectorComposer(
-    val root: VNode,
-    slotTable: SlotTable,
-    recomposer: Recomposer
-) : Composer<VNode>(slotTable, Applier(root, VectorApplyAdapter()), recomposer) {
-    inline fun <T : VNode> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: () -> T,
-        update: VectorUpdater<VNode>.() -> Unit
-    ) {
-        startNode(key)
-
-        @Suppress("UNCHECKED_CAST")
-        val node = if (inserting) {
-            ctor().also {
-                emitNode(it)
-            }
-        } else {
-            useNode()
-        }
-
-        VectorUpdater(this, node).update()
-        endNode()
+class VectorApplier(root: VNode) : AbstractApplier<VNode>(root) {
+    override fun insert(index: Int, instance: VNode) {
+        current.asGroup().insertAt(index, instance)
     }
 
-    inline fun emit(
-        key: Any,
-        /*crossinline*/
-        ctor: () -> GroupComponent,
-        update: VectorUpdater<GroupComponent>.() -> Unit,
-        children: () -> Unit
-    ) {
-        startNode(key)
-
-        @Suppress("UNCHECKED_CAST")
-        val node = if (inserting) {
-            ctor().also {
-                emitNode(it)
-            }
-        } else {
-            useNode() as GroupComponent
-        }
-
-        VectorUpdater(this, node).update()
-        children()
-        endNode()
-    }
-}
-
-internal class VectorApplyAdapter : ApplyAdapter<VNode> {
-    override fun VNode.start(instance: VNode) {
-        // NO-OP
+    override fun remove(index: Int, count: Int) {
+        current.asGroup().remove(index, count)
     }
 
-    override fun VNode.insertAt(index: Int, instance: VNode) {
-        obtainGroup().insertAt(index, instance)
+    override fun move(from: Int, to: Int, count: Int) {
+        current.asGroup().move(from, to, count)
     }
 
-    override fun VNode.removeAt(index: Int, count: Int) {
-        obtainGroup().remove(index, count)
-    }
-
-    override fun VNode.move(from: Int, to: Int, count: Int) {
-        obtainGroup().move(from, to, count)
-    }
-
-    override fun VNode.end(instance: VNode, parent: VNode) {
-        // NO-OP
-    }
-
-    fun VNode.obtainGroup(): GroupComponent {
+    private fun VNode.asGroup(): GroupComponent {
         return when (this) {
             is GroupComponent -> this
-            else -> throw IllegalArgumentException("Cannot only insert VNode into Group")
+            else -> error("Cannot only insert VNode into Group")
         }
     }
 }
-
-typealias VectorUpdater<T> = ComposerUpdater<VNode, T>
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt
index 6973254..6c71636 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt
@@ -59,7 +59,7 @@
     viewportWidth: Float = Float.NaN,
     viewportHeight: Float = Float.NaN,
     name: String = RootGroupName,
-    children: @Composable VectorScope.(viewportWidth: Float, viewportHeight: Float) -> Unit
+    children: @Composable (viewportWidth: Float, viewportHeight: Float) -> Unit
 ): VectorPainter {
     val density = DensityAmbient.current
     val widthPx = with(density) { defaultWidth.toPx() }
@@ -137,7 +137,7 @@
     defaultHeight: Float,
     viewportWidth: Float = defaultWidth,
     viewportHeight: Float = defaultHeight,
-    children: @Composable VectorScope.(viewportWidth: Float, viewportHeight: Float) -> Unit
+    children: @Composable (viewportWidth: Float, viewportHeight: Float) -> Unit
 ): VectorComponent {
     val vector =
         remember(name, viewportWidth, viewportHeight) {
@@ -171,7 +171,7 @@
  * the tree structure
  */
 @Composable
-private fun VectorScope.RenderVectorGroup(group: VectorGroup) {
+private fun RenderVectorGroup(group: VectorGroup) {
     for (vectorNode in group) {
         if (vectorNode is VectorPath) {
             Path(
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt
index 760e565..8ce0ef6b 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.text.InputType
 import android.view.View
+import android.view.ViewTreeObserver
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
 import android.view.inputmethod.InputMethodManager
@@ -45,11 +46,31 @@
     private var imeAction = ImeAction.Unspecified
     private var ic: RecordingInputConnection? = null
 
+    private var focusedRect: android.graphics.Rect? = null
+
     /**
      * The editable buffer used for BaseInputConnection.
      */
     private lateinit var imm: InputMethodManager
 
+    private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
+        // focusedRect is null if there is not ongoing text input session. So safe to request
+        // latest focused rectangle whenever global layout has changed.
+        focusedRect?.let { view.requestRectangleOnScreen(it) }
+    }
+
+    init {
+        view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
+            override fun onViewDetachedFromWindow(v: View?) {
+                v?.rootView?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener)
+            }
+
+            override fun onViewAttachedToWindow(v: View?) {
+                v?.rootView?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener)
+            }
+        })
+    }
+
     /**
      * Creates new input connection.
      */
@@ -104,6 +125,7 @@
         editorHasFocus = false
         onEditCommand = {}
         onImeActionPerformed = {}
+        focusedRect = null
 
         imm.restartInput(view)
         editorHasFocus = false
@@ -123,11 +145,22 @@
     }
 
     override fun notifyFocusedRect(rect: Rect) {
-        view.requestRectangleOnScreen(android.graphics.Rect(
+        focusedRect = android.graphics.Rect(
             rect.left.roundToInt(),
             rect.top.roundToInt(),
             rect.right.roundToInt(),
-            rect.bottom.roundToInt()))
+            rect.bottom.roundToInt()
+        )
+
+        // Requesting rectangle too early after obtaining focus may bring view into wrong place
+        // probably due to transient IME inset change. We don't know the correct timing of calling
+        // requestRectangleOnScreen API, so try to call this API only after the IME is ready to
+        // use, i.e. InputConnection has created.
+        // Even if we miss all the timing of requesting rectangle during initial text field focus,
+        // focused rectangle will be requested when software keyboard has shown.
+        if (ic == null) {
+            view.requestRectangleOnScreen(focusedRect)
+        }
     }
 
     /**
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiApplier.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiApplier.kt
new file mode 100644
index 0000000..046ab03
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiApplier.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalComposeApi::class)
+package androidx.ui.node
+
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.Applier
+import androidx.compose.ExperimentalComposeApi
+import androidx.ui.core.LayoutNode
+import androidx.ui.viewinterop.AndroidViewHolder
+
+// TODO: evaluate if this class is necessary or not
+private class Stack<T> {
+    private val backing = ArrayList<T>()
+
+    val size: Int get() = backing.size
+
+    fun push(value: T) = backing.add(value)
+    fun pop(): T = backing.removeAt(size - 1)
+    fun peek(): T = backing[size - 1]
+    fun isEmpty() = backing.isEmpty()
+    fun isNotEmpty() = !isEmpty()
+    fun clear() = backing.clear()
+}
+
+class UiApplier(root: Any) : Applier<Any> {
+    private val stack = Stack<Any>()
+    private data class PendingInsert(val index: Int, val instance: Any)
+    // TODO(b/159073250): remove
+    private val pendingInserts = Stack<PendingInsert>()
+
+    private fun invalidNode(node: Any): Nothing =
+        error("Unsupported node type ${node.javaClass.simpleName}")
+
+    override var current: Any = root
+        private set
+
+    override fun down(node: Any) {
+        stack.push(current)
+        current = node
+    }
+
+    override fun up() {
+        val instance = current
+        val parent = stack.pop()
+        current = parent
+        // TODO(lmr): We should strongly consider removing this ViewAdapter concept
+        val adapter = when (instance) {
+            is View -> instance.getViewAdapterIfExists()
+            else -> null
+        }
+        if (pendingInserts.isNotEmpty()) {
+            val pendingInsert = pendingInserts.peek()
+            if (pendingInsert.instance == instance) {
+                val index = pendingInsert.index
+                pendingInserts.pop()
+
+                when (parent) {
+                    is ViewGroup ->
+                        when (instance) {
+                            is View -> {
+                                adapter?.willInsert(instance, parent)
+                                parent.addView(instance, index)
+                                adapter?.didInsert(instance, parent)
+                            }
+//                            is LayoutNode -> {
+//                                val adaptedView = adapters?.adapt(parent, instance) as? View
+//                                    ?: error(
+//                                        "Could not convert ${
+//                                        instance.javaClass.simpleName
+//                                        } to a View"
+//                                    )
+//                                adapter?.willInsert(adaptedView, parent)
+//                                parent.addView(adaptedView, index)
+//                                adapter?.didInsert(adaptedView, parent)
+//                            }
+                            else -> invalidNode(instance)
+                        }
+                    is LayoutNode ->
+                        when (instance) {
+                            is View -> {
+                                // Wrap the instance in an AndroidViewHolder, unless the instance
+                                // itself is already one.
+                                val androidViewHolder =
+                                    if (instance is AndroidViewHolder) {
+                                        instance
+                                    } else {
+                                        AndroidViewHolder(instance.context).apply {
+                                            view = instance
+                                        }
+                                    }
+
+                                parent.insertAt(index, androidViewHolder.toLayoutNode())
+                            }
+                            is LayoutNode -> parent.insertAt(index, instance)
+                            else -> invalidNode(instance)
+                        }
+                    else -> invalidNode(parent)
+                }
+                return
+            }
+        }
+        if (parent is ViewGroup)
+            adapter?.didUpdate(instance as View, parent)
+    }
+
+    override fun insert(index: Int, instance: Any) {
+        pendingInserts.push(
+            PendingInsert(
+                index,
+                instance
+            )
+        )
+    }
+
+    override fun remove(index: Int, count: Int) {
+        when (val node = current) {
+            is ViewGroup -> node.removeViews(index, count)
+            is LayoutNode -> node.removeAt(index, count)
+            else -> invalidNode(node)
+        }
+    }
+
+    override fun move(from: Int, to: Int, count: Int) {
+        when (val node = current) {
+            is ViewGroup -> {
+                if (from > to) {
+                    var currentFrom = from
+                    var currentTo = to
+                    repeat(count) {
+                        val view = node.getChildAt(currentFrom)
+                        node.removeViewAt(currentFrom)
+                        node.addView(view, currentTo)
+                        currentFrom++
+                        currentTo++
+                    }
+                } else {
+                    repeat(count) {
+                        val view = node.getChildAt(from)
+                        node.removeViewAt(from)
+                        node.addView(view, to - 1)
+                    }
+                }
+            }
+            is LayoutNode -> {
+                node.move(from, to, count)
+            }
+            else -> invalidNode(node)
+        }
+    }
+
+    override fun reset() {
+        stack.clear()
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiComposer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiComposer.kt
deleted file mode 100644
index a0686f6..0000000
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiComposer.kt
+++ /dev/null
@@ -1,247 +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.
- */
-
-@file:OptIn(ExperimentalComposeApi::class, ComposeCompilerApi::class)
-package androidx.ui.node
-
-import android.content.Context
-import android.view.View
-import android.view.ViewGroup
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
-import androidx.compose.ComposeCompilerApi
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
-import androidx.compose.ExperimentalComposeApi
-import androidx.compose.FrameManager
-import androidx.compose.Recomposer
-import androidx.compose.SlotTable
-import androidx.ui.core.LayoutNode
-import androidx.ui.viewinterop.AndroidViewHolder
-
-// TODO: evaluate if this class is necessary or not
-private class Stack<T> {
-    private val backing = ArrayList<T>()
-
-    val size: Int get() = backing.size
-
-    fun push(value: T) = backing.add(value)
-    fun pop(): T = backing.removeAt(size - 1)
-    fun peek(): T = backing[size - 1]
-    fun isEmpty() = backing.isEmpty()
-    fun isNotEmpty() = !isEmpty()
-    fun clear() = backing.clear()
-}
-
-private fun invalidNode(node: Any): Nothing =
-    error("Unsupported node type ${node.javaClass.simpleName}")
-
-internal class UiApplyAdapter : ApplyAdapter<Any> {
-    private data class PendingInsert(val index: Int, val instance: Any)
-
-    private val pendingInserts =
-        Stack<PendingInsert>()
-
-    override fun Any.start(instance: Any) {}
-    override fun Any.insertAt(index: Int, instance: Any) {
-        pendingInserts.push(
-            PendingInsert(
-                index,
-                instance
-            )
-        )
-    }
-
-    override fun Any.removeAt(index: Int, count: Int) {
-        when (this) {
-            is ViewGroup -> removeViews(index, count)
-            is LayoutNode -> removeAt(index, count)
-            else -> invalidNode(this)
-        }
-    }
-
-    override fun Any.move(from: Int, to: Int, count: Int) {
-        when (this) {
-            is ViewGroup -> {
-                if (from > to) {
-                    var currentFrom = from
-                    var currentTo = to
-                    repeat(count) {
-                        val view = getChildAt(currentFrom)
-                        removeViewAt(currentFrom)
-                        addView(view, currentTo)
-                        currentFrom++
-                        currentTo++
-                    }
-                } else {
-                    repeat(count) {
-                        val view = getChildAt(from)
-                        removeViewAt(from)
-                        addView(view, to - 1)
-                    }
-                }
-            }
-            is LayoutNode -> {
-                move(from, to, count)
-            }
-            else -> invalidNode(this)
-        }
-    }
-
-    override fun Any.end(instance: Any, parent: Any) {
-        val adapter = when (instance) {
-            is View -> instance.getViewAdapterIfExists()
-            else -> null
-        }
-        if (pendingInserts.isNotEmpty()) {
-            val pendingInsert = pendingInserts.peek()
-            if (pendingInsert.instance == instance) {
-                val index = pendingInsert.index
-                pendingInserts.pop()
-
-                when (parent) {
-                    is ViewGroup ->
-                        when (instance) {
-                            is View -> {
-                                adapter?.willInsert(instance, parent)
-                                parent.addView(instance, index)
-                                adapter?.didInsert(instance, parent)
-                            }
-//                            is LayoutNode -> {
-//                                val adaptedView = adapters?.adapt(parent, instance) as? View
-//                                    ?: error(
-//                                        "Could not convert ${
-//                                        instance.javaClass.simpleName
-//                                        } to a View"
-//                                    )
-//                                adapter?.willInsert(adaptedView, parent)
-//                                parent.addView(adaptedView, index)
-//                                adapter?.didInsert(adaptedView, parent)
-//                            }
-                            else -> invalidNode(instance)
-                        }
-                    is LayoutNode ->
-                        when (instance) {
-                            is View -> {
-                                // Wrap the instance in an AndroidViewHolder, unless the instance
-                                // itself is already one.
-                                val androidViewHolder =
-                                    if (instance is AndroidViewHolder) {
-                                        instance
-                                    } else {
-                                        AndroidViewHolder(instance.context).apply {
-                                            view = instance
-                                        }
-                                    }
-
-                                parent.insertAt(index, androidViewHolder.toLayoutNode())
-                            }
-                            is LayoutNode -> parent.insertAt(index, instance)
-                            else -> invalidNode(instance)
-                        }
-                    else -> invalidNode(parent)
-                }
-                return
-            }
-        }
-        if (parent is ViewGroup)
-            adapter?.didUpdate(instance as View, parent)
-    }
-}
-
-class UiComposer(
-    val context: Context,
-    val root: Any,
-    slotTable: SlotTable,
-    recomposer: Recomposer
-) : Composer<Any>(
-    slotTable,
-    Applier(
-        root,
-        UiApplyAdapter()
-    ),
-    recomposer
-) {
-    init {
-        FrameManager.ensureStarted()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    inline fun <T : View> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: (context: Context) -> T,
-        update: UiUpdater<T>.() -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor(context).also { emitNode(it) }
-        else useNode() as T
-        UiUpdater(this, node).update()
-        endNode()
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    inline fun <T : ViewGroup> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: (context: Context) -> T,
-        update: UiUpdater<T>.() -> Unit,
-        children: () -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor(context).also { emitNode(it) }
-        else useNode() as T
-        UiUpdater(this, node).update()
-        children()
-        endNode()
-    }
-
-    // There is a compilation error if I change T -> LayoutNode, so I
-    // just suppressed the warning
-    @Suppress("UNCHECKED_CAST", "FINAL_UPPER_BOUND")
-    inline fun <T : LayoutNode> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: () -> T,
-        update: UiUpdater<T>.() -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor().also { emitNode(it) }
-        else useNode() as T
-        UiUpdater(this, node).update()
-        endNode()
-    }
-
-    // There is a compilation error if I change T -> LayoutNode, so I
-    // just suppressed the warning
-    @Suppress("UNCHECKED_CAST", "FINAL_UPPER_BOUND")
-    inline fun <T : LayoutNode> emit(
-        key: Any,
-        /*crossinline*/
-        ctor: () -> T,
-        update: UiUpdater<T>.() -> Unit,
-        children: () -> Unit
-    ) {
-        startNode(key)
-        val node = if (inserting) ctor().also { emitNode(it) }
-        else useNode() as T
-        UiUpdater(this, node).update()
-        children()
-        endNode()
-    }
-}
-
-typealias UiUpdater<T> = ComposerUpdater<Any, T>
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/semantics/Semantics.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/semantics/Semantics.kt
deleted file mode 100644
index f1cebac..0000000
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/semantics/Semantics.kt
+++ /dev/null
@@ -1,49 +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.semantics
-
-import androidx.compose.Composable
-import androidx.ui.core.PassThroughLayout
-import androidx.ui.core.Modifier
-import androidx.ui.core.semantics.semantics
-
-@Deprecated("Semantics() is deprecated. Use Modifier.semantics() instead.")
-@Composable
-fun Semantics(
-    /**
-     * Legacy parameter, no longer has any effect.
-     */
-    @Suppress("UNUSED_PARAMETER") container: Boolean = false,
-    /**
-     * Whether the semantic information provided by the owning component and
-     * all of its descendants should be treated as one logical entity.
-     *
-     * If set to true, the descendants of the owning component's
-     * [SemanticsNode] will merge their semantic information into the
-     * [SemanticsNode] representing the owning component.
-     */
-    mergeAllDescendants: Boolean = false,
-    properties: (SemanticsPropertyReceiver.() -> Unit)? = null,
-    children: @Composable () -> Unit
-) {
-    @Suppress("DEPRECATION")
-    PassThroughLayout(
-        Modifier.semantics(
-            applyToChildLayoutNode = true,
-            mergeAllDescendants = mergeAllDescendants,
-            properties = properties),
-        children)
-}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt
index 119ce7a..7187ac5 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt
@@ -26,6 +26,9 @@
 import androidx.compose.currentComposer
 import androidx.ui.core.Modifier
 import androidx.ui.core.materialize
+import androidx.compose.emit
+import androidx.ui.core.ContextAmbient
+import androidx.ui.node.UiApplier
 
 /**
  * Composes an Android [View] given a layout resource [resId]. The method handles the inflation
@@ -42,10 +45,15 @@
     modifier: Modifier = Modifier,
     postInflationCallback: (View) -> Unit = { _ -> }
 ) {
-    AndroidViewHolder(
-        postInflationCallback = postInflationCallback,
-        resId = resId,
-        modifier = currentComposer.materialize(modifier)
+    val context = ContextAmbient.current
+    val materialized = currentComposer.materialize(modifier)
+    emit<AndroidViewHolder, UiApplier>(
+        ctor = { AndroidViewHolder(context) },
+        update = {
+            set(postInflationCallback) { this.postInflationCallback = it }
+            set(resId) { this.resId = it }
+            set(materialized) { this.modifier = it }
+        }
     )
 }
 
@@ -57,7 +65,15 @@
  */
 @Composable
 fun AndroidView(view: View, modifier: Modifier = Modifier) {
-    AndroidViewHolder(view = view, modifier = currentComposer.materialize(modifier))
+    val context = ContextAmbient.current
+    val materialized = currentComposer.materialize(modifier)
+    emit<AndroidViewHolder, UiApplier>(
+        ctor = { AndroidViewHolder(context) },
+        update = {
+            set(view) { this.view = it }
+            set(materialized) { this.modifier = it }
+        }
+    )
 }
 
 // Open to be mockable in tests.
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/EmitView.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/EmitView.kt
new file mode 100644
index 0000000..3b08b43
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/EmitView.kt
@@ -0,0 +1,77 @@
+/*
+ * 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.viewinterop
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.Composable
+import androidx.compose.emit
+import androidx.ui.core.ContextAmbient
+import androidx.ui.node.UiApplier
+
+/**
+ * Emit a view into the current composition.
+ *
+ * @sample androidx.ui.core.samples.EmitViewButtonSample
+ *
+ * @param ctor The constructor of the view with a single [Context] parameter.
+ * @param update A function which will execute when the composition is applied, with the emitted
+ * view instance passed in. This function is expected to be used to handle the "update" logic to
+ * handle any changes.
+ */
+@Composable
+fun <T : View> emitView(
+    ctor: (Context) -> T,
+    update: (T) -> Unit
+) {
+    val context = ContextAmbient.current
+    emit<T, UiApplier>(
+        ctor = { ctor(context) },
+        update = {
+            reconcile(update)
+        }
+    )
+}
+
+/**
+ * Emit a ViewGroup into the current composition, with the emitted nodes of [children] as the
+ * content.
+ *
+ * @sample androidx.ui.core.samples.EmitViewLinearLayoutSample
+ *
+ * @param ctor The constructor of the view with a single [Context] parameter.
+ * @param update A function which will execute when the composition is applied, with the emitted
+ * view instance passed in. This function is expected to be used to handle the "update" logic to
+ * handle any changes.
+ * @param children the composable content that will emit the "children" of this view.
+ */
+@Composable
+fun <T : ViewGroup> emitView(
+    ctor: (Context) -> T,
+    update: (T) -> Unit,
+    children: @Composable () -> Unit
+) {
+    val context = ContextAmbient.current
+    emit<T, UiApplier>(
+        ctor = { ctor(context) },
+        update = {
+            reconcile(update)
+        },
+        children = children
+    )
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt
index 8da03e3..5baa9ce 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt
@@ -17,14 +17,15 @@
 package androidx.ui.autofill
 
 import android.app.Activity
-import androidx.ui.geometry.Rect
+import android.graphics.Rect as AndroidRect
 import android.view.View
 import android.view.autofill.AutofillManager
 import androidx.test.filters.SmallTest
 import androidx.ui.ComposeUiRobolectricTestRunner
+import androidx.ui.core.toComposeRect
+import androidx.ui.geometry.Rect
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
-import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.ExpectedException
@@ -69,7 +70,6 @@
         assertThat(view.importantForAutofill).isEqualTo(View.IMPORTANT_FOR_AUTOFILL_YES)
     }
 
-    @Ignore("b/159210000")
     @Test
     fun requestAutofillForNode_calls_notifyViewEntered() {
         // Arrange.
@@ -121,8 +121,8 @@
     val viewExitedStats = mutableListOf<NotifyViewExited>()
 
     @Implementation
-    fun notifyViewEntered(view: View, virtualId: Int, rect: Rect) {
-        viewEnteredStats += NotifyViewEntered(view, virtualId, rect)
+    fun notifyViewEntered(view: View, virtualId: Int, rect: AndroidRect) {
+        viewEnteredStats += NotifyViewEntered(view, virtualId, rect.toComposeRect())
     }
 
     @Implementation
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt
index 2d3b191..a724024 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt
@@ -17,15 +17,14 @@
 package androidx.ui.core
 
 import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
 import androidx.compose.Composable
 import androidx.compose.Composer
-import androidx.compose.CompositionFrameClock
 import androidx.compose.ExperimentalComposeApi
 import androidx.compose.InternalComposeApi
 import androidx.compose.Recomposer
 import androidx.compose.SlotTable
 import androidx.compose.currentComposer
+import androidx.compose.dispatch.MonotonicFrameClock
 import androidx.compose.invalidate
 import androidx.compose.remember
 import androidx.compose.withRunningRecomposer
@@ -49,8 +48,6 @@
 @OptIn(InternalComposeApi::class)
 class ComposedModifierTest {
 
-    private val composer: Composer<*> get() = error("should not be called")
-
     /**
      * Confirm that a [composed] modifier correctly constructs separate instances when materialized
      */
@@ -201,29 +198,27 @@
     }
 }
 
-@OptIn(InternalComposeApi::class)
+@OptIn(InternalComposeApi::class, ExperimentalComposeApi::class)
 private fun compose(
     recomposer: Recomposer,
     block: @Composable () -> Unit
-): Composer<Unit> = UnitComposer(recomposer).apply {
-    compose(block)
-    applyChanges()
-    slotTable.verifyWellFormed()
+): Composer<Unit> {
+    return Composer(
+        SlotTable(),
+        EmptyApplier(),
+        recomposer
+    ).apply {
+        composeRoot {
+            @Suppress("UNCHECKED_CAST")
+            val fn = block as (Composer<*>, Int, Int) -> Unit
+            fn(this, 0, 0)
+        }
+        applyChanges()
+        slotTable.verifyWellFormed()
+    }
 }
 
-/**
- * This ApplyAdapter does nothing. These tests only confirm modifier materialization.
- */
-@OptIn(ExperimentalComposeApi::class)
-private object UnitApplierAdapter : ApplyAdapter<Unit> {
-    override fun Unit.start(instance: Unit) {}
-    override fun Unit.insertAt(index: Int, instance: Unit) {}
-    override fun Unit.removeAt(index: Int, count: Int) {}
-    override fun Unit.move(from: Int, to: Int, count: Int) {}
-    override fun Unit.end(instance: Unit, parent: Unit) {}
-}
-
-private class TestFrameClock : CompositionFrameClock {
+private class TestFrameClock : MonotonicFrameClock {
 
     private val frameCh = Channel<Long>()
 
@@ -235,16 +230,18 @@
 }
 
 @OptIn(ExperimentalComposeApi::class)
-private class UnitComposer(recomposer: Recomposer) : Composer<Unit>(
-    SlotTable(),
-    Applier(Unit, UnitApplierAdapter),
-    recomposer
-) {
-    fun compose(composable: @Composable () -> Unit) {
-        composeRoot {
-            @Suppress("UNCHECKED_CAST")
-            val fn = composable as (Composer<*>, Int, Int) -> Unit
-            fn(this@UnitComposer, 0, 0)
-        }
+class EmptyApplier : Applier<Unit> {
+    override val current: Unit = Unit
+    override fun down(node: Unit) {}
+    override fun up() {}
+    override fun insert(index: Int, instance: Unit) {
+        error("Unexpected")
     }
-}
\ No newline at end of file
+    override fun remove(index: Int, count: Int) {
+        error("Unexpected")
+    }
+    override fun move(from: Int, to: Int, count: Int) {
+        error("Unexpected")
+    }
+    override fun reset() {}
+}
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt
index 7603287..03464d8 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt
@@ -31,6 +31,7 @@
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertNull
+import org.junit.Assert.assertSame
 import org.junit.Assert.assertTrue
 import org.junit.Rule
 import org.junit.Test
@@ -656,6 +657,45 @@
         assertFalse(layoutNode.coordinates.isAttached)
     }
 
+    // The LayoutNodeWrapper should be reused when it has been replaced with the same type
+    @Test
+    fun layoutNodeWrapperSameWithReplacementModifier() {
+        val layoutNode = LayoutNode()
+        val drawModifier = Modifier.drawBehind { }
+
+        layoutNode.modifier = drawModifier
+        val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+        assertFalse(oldLayoutNodeWrapper.isAttached)
+
+        layoutNode.attach(mockOwner())
+        assertTrue(oldLayoutNodeWrapper.isAttached)
+
+        layoutNode.modifier = Modifier.drawBehind { }
+        val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+        assertSame(newLayoutNodeWrapper, oldLayoutNodeWrapper)
+    }
+
+    // The LayoutNodeWrapper should be reused when it has been replaced with the same type,
+    // even with multiple LayoutNodeWrappers for one modifier.
+    @Test
+    fun layoutNodeWrapperSameWithReplacementMultiModifier() {
+        class TestModifier : DrawModifier, DrawLayerModifier {
+            override fun ContentDrawScope.draw() {
+                drawContent()
+            }
+        }
+        val layoutNode = LayoutNode()
+
+        layoutNode.modifier = TestModifier()
+        val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+        val oldLayoutNodeWrapper2 = oldLayoutNodeWrapper.wrapped
+        layoutNode.modifier = TestModifier()
+        val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+        val newLayoutNodeWrapper2 = newLayoutNodeWrapper.wrapped
+        assertSame(newLayoutNodeWrapper, oldLayoutNodeWrapper)
+        assertSame(newLayoutNodeWrapper2, oldLayoutNodeWrapper2)
+    }
+
     // The LayoutNodeWrapper should be detached when it has been replaced.
     @Test
     fun layoutNodeWrapperAttachedWhenLayoutNodeAttached() {
@@ -669,7 +709,7 @@
         layoutNode.attach(mockOwner())
         assertTrue(oldLayoutNodeWrapper.isAttached)
 
-        layoutNode.modifier = Modifier.drawBehind { }
+        layoutNode.modifier = Modifier.drawLayer()
         val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
         assertTrue(newLayoutNodeWrapper.isAttached)
         assertFalse(oldLayoutNodeWrapper.isAttached)
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt
index cd4a7fc..1de3982 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt
@@ -14,11 +14,18 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalPointerInput::class)
+@file:Suppress("PrivatePropertyName")
+
 package androidx.ui.core.gesture
 
 import androidx.ui.core.Direction
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.consumeDownChange
+import androidx.ui.core.gesture.scrollorientationlocking.InternalScrollOrientationLocker
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
+import androidx.ui.core.gesture.scrollorientationlocking.ShareScrollOrientationLockerEvent
 import androidx.ui.testutils.consume
 import androidx.ui.testutils.down
 import androidx.ui.testutils.invokeOverAllPasses
@@ -29,6 +36,7 @@
 import androidx.ui.unit.Duration
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.mock
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -66,8 +74,9 @@
         canDragDirections.clear()
         filter =
             DragSlopExceededGestureFilter(TestTouchSlop.toFloat())
-        filter.canDrag = canDrag
+        filter.setDraggableData(null, canDrag)
         filter.onDragSlopExceeded = onDragSlopExceeded
+        filter.scrollOrientationLocker = ScrollOrientationLocker(mock())
     }
 
     // Verify the circumstances under which canDrag should not be called.
@@ -881,6 +890,219 @@
         assertThat(onDragSlopExceededCallCount).isEqualTo(2)
     }
 
+    // Orientation tests
+
+    // Tests that verify correct behavior when orientation is set.
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementVertical_canDragNotCalled() {
+        filter.setDraggableData(Orientation.Horizontal, canDrag)
+
+        val down = down(0)
+        filter::onPointerInput.invokeOverAllPasses(down)
+        val move1 = down.moveBy(Duration(milliseconds = 10), 0f, 1f)
+        filter::onPointerInput.invokeOverAllPasses(move1)
+        val move2 = down.moveBy(Duration(milliseconds = 10), 0f, -1f)
+        filter::onPointerInput.invokeOverAllPasses(move2)
+
+        assertThat(canDragDirections).isEmpty()
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsHorizontal_canDragNotCalled() {
+        filter.setDraggableData(Orientation.Vertical, canDrag)
+
+        val down = down(0)
+        filter::onPointerInput.invokeOverAllPasses(down)
+        val move1 = down.moveBy(Duration(milliseconds = 10), 1f, 0f)
+        filter::onPointerInput.invokeOverAllPasses(move1)
+        val move2 = down.moveBy(Duration(milliseconds = 10), -1f, 0f)
+        filter::onPointerInput.invokeOverAllPasses(move2)
+
+        assertThat(canDragDirections).isEmpty()
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementHorizontal_canDragCalled() {
+        filter.setDraggableData(Orientation.Horizontal, canDrag)
+
+        val down = down(0)
+        filter::onPointerInput.invokeOverAllPasses(down)
+        val move1 = down.moveBy(Duration(milliseconds = 10), 1f, 0f)
+        filter::onPointerInput.invokeOverAllPasses(move1)
+        val move2 = down.moveBy(Duration(milliseconds = 10), -1f, 0f)
+        filter::onPointerInput.invokeOverAllPasses(move2)
+
+        // 2 for each because canDrag is currently checked on both postUp and postDown
+        assertThat(canDragDirections.filter { it == Direction.LEFT }).hasSize(2)
+        assertThat(canDragDirections.filter { it == Direction.RIGHT }).hasSize(2)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsVertical_canDragCalled() {
+        filter.setDraggableData(Orientation.Vertical, canDrag)
+
+        val down = down(0)
+        filter::onPointerInput.invokeOverAllPasses(down)
+        val move1 = down.moveBy(Duration(milliseconds = 10), 0f, 1f)
+        filter::onPointerInput.invokeOverAllPasses(move1)
+        val move2 = down.moveBy(Duration(milliseconds = 10), 0f, -1f)
+        filter::onPointerInput.invokeOverAllPasses(move2)
+
+        // 2 for each because canDrag is currently checked on both postUp and postDown
+        assertThat(canDragDirections.filter { it == Direction.UP }).hasSize(2)
+        assertThat(canDragDirections.filter { it == Direction.DOWN }).hasSize(2)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMoveLeftPassedSlop_onTouchSlopExceededCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, -1, 0, 1)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMoveUpPassedSlop_onTouchSlopExceededNotCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, 0, -1, 0)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMoveRightPassedSlop_onTouchSlopExceededCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, 1, 0, 1)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMoveDownPassedSlop_onTouchSlopExceededNotCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, 0, 1, 0)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMoveLeftPassedSlop_onTouchSlopExceededNotCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, -1, 0, 0)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMoveUpPassedSlop_onTouchSlopExceededCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, 0, -1, 1)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMoveRightPassedSlop_onTouchSlopExceededNotCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, 1, 0, 0)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMoveDownPassedSlop_onTouchSlopExceededCalled() {
+        onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, 0, 1, 1)
+    }
+
+    private fun onPointerInput_filterHasOrientationMovePassedSlop(
+        filterOrientation: Orientation,
+        horizontalDirection: Int,
+        verticalDirection: Int,
+        expectecdOnDragSlopExceededCallCount: Int
+    ) {
+        val beyondSlop = TestTouchSlop + TinyNum
+
+        filter.setDraggableData(filterOrientation, canDrag)
+
+        val down = down(0)
+        filter::onPointerInput.invokeOverAllPasses(down)
+        val move = down.moveBy(
+            Duration(milliseconds = 100),
+            horizontalDirection * beyondSlop,
+            verticalDirection * beyondSlop
+        )
+        filter::onPointerInput.invokeOverAllPasses(move)
+
+        assertThat(onDragSlopExceededCallCount).isEqualTo(expectecdOnDragSlopExceededCallCount)
+    }
+
+    @Test
+    fun onPointerInput_filterHorizontalPointerVerticalMovesLeftPastSlop_callBackNotCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Horizontal, Orientation.Vertical, -1, 0, 0
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterHorizontalPointerVerticalMovesRightPastSlop_callBackNotCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Horizontal, Orientation.Vertical, 1, 0, 0
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterHorizontalPointerHorizontalMovesLeftPastSlop_callBackCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Horizontal, Orientation.Horizontal, -1, 0, 1
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterHorizontalPointerHorizontallMovesRightPastSlop_callBackCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Horizontal, Orientation.Horizontal, 1, 0, 1
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterVerticalPointerHorizontalMovesUpPastSlop_callBackNotCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Vertical, Orientation.Horizontal, 0, -1, 0
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterVerticalPointerHorizontalMovesDownPastSlop_callBackNotCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Vertical, Orientation.Horizontal, 0, 1, 0
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterVerticalPointerVerticalMovesUpPastSlop_callBackCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Vertical, Orientation.Vertical, 0, -1, 1
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterVerticalPointerVerticalMovesDownPastSlop_callBackCalled() {
+        onPointerInput_pointerIsLockedMovesPassedSlop(
+            Orientation.Vertical, Orientation.Vertical, 0, 1, 1
+        )
+    }
+
+    private fun onPointerInput_pointerIsLockedMovesPassedSlop(
+        filterOrientation: Orientation,
+        lockedOrientation: Orientation,
+        horizontalDirection: Int,
+        verticalDirection: Int,
+        expectedOnDragSlopExceededCallCount: Int
+    ) {
+        val beyondSlop = TestTouchSlop + TinyNum
+
+        filter.onInit(mock())
+        val scrollOrientationLocker = InternalScrollOrientationLocker()
+        filter::onCustomEvent.invokeOverAllPasses(
+            ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+        )
+
+        filter.setDraggableData(filterOrientation, canDrag)
+
+        val down = down(0)
+        filter::onPointerInput.invokeOverAllPasses(down)
+        val move = down.moveBy(
+            Duration(milliseconds = 100),
+            horizontalDirection * beyondSlop,
+            verticalDirection * beyondSlop
+        )
+        scrollOrientationLocker.attemptToLockPointers(listOf(move), lockedOrientation)
+
+        filter::onPointerInput.invokeOverAllPasses(move)
+
+        assertThat(onDragSlopExceededCallCount).isEqualTo(expectedOnDragSlopExceededCallCount)
+    }
+
     // Verification that cancellation behavior is correct.
 
     @Test
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
index df409af..29dcf18 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
@@ -16,9 +16,13 @@
 
 package androidx.ui.core.gesture
 
+import androidx.ui.core.CustomEventDispatcher
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.anyPositionChangeConsumed
 import androidx.ui.core.consumePositionChange
+import androidx.ui.core.gesture.scrollorientationlocking.InternalScrollOrientationLocker
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ShareScrollOrientationLockerEvent
 import androidx.ui.geometry.Offset
 import androidx.ui.testutils.consume
 import androidx.ui.testutils.down
@@ -31,6 +35,11 @@
 import androidx.ui.unit.IntSize
 import androidx.ui.unit.milliseconds
 import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.argumentCaptor
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.reset
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -48,6 +57,7 @@
     private lateinit var filter: RawDragGestureFilter
     private lateinit var dragObserver: MockDragObserver
     private lateinit var log: MutableList<LogItem>
+    private lateinit var customEventDispatcher: CustomEventDispatcher
     private var dragStartBlocked = true
 
     @Before
@@ -57,6 +67,8 @@
         filter = RawDragGestureFilter()
         filter.canStartDragging = { !dragStartBlocked }
         filter.dragObserver = dragObserver
+        customEventDispatcher = mock()
+        filter.onInit(customEventDispatcher)
     }
 
     // Verify the circumstances under which onStart/OnDrag should not be called.
@@ -371,11 +383,14 @@
     ) {
         log.clear()
 
-        var change = down(0, 0.milliseconds)
+        var time = 0.milliseconds
+
+        var change = down(0, time)
         filter::onPointerInput.invokeOverAllPasses(change)
         dragStartBlocked = false
 
         repeat(11) {
+            time += 10.milliseconds
             change = change.moveBy(
                 10.milliseconds,
                 incrementPerMilliX,
@@ -384,7 +399,8 @@
             filter::onPointerInput.invokeOverAllPasses(change)
         }
 
-        change = change.up(20.milliseconds)
+        time += 10.milliseconds
+        change = change.up(time)
         filter::onPointerInput.invokeOverAllPasses(change)
 
         val loggedStops = log.filter { it.methodName == "onStop" }
@@ -575,6 +591,440 @@
             .isEqualTo(Offset(3f, 4f))
     }
 
+    @Test
+    fun onPointerInput_hasOrientationDownEvent_customEventDispatchedOnceDuringInitialDown() {
+
+        // Arrange
+
+        filter.orientation = Orientation.Vertical
+
+        val down = down(0)
+
+        // Act / Verify 1
+
+        filter::onPointerInput.invokeOverPasses(down, PointerEventPass.InitialDown)
+        argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+            assertThat(allValues).hasSize(1)
+            assertThat(allValues.first().scrollOrientationLocker).isNotNull()
+        }
+
+        reset(customEventDispatcher)
+
+        // Act / Verify 1
+        filter::onPointerInput.invokeOverPasses(
+            down,
+            PointerEventPass.PreUp,
+            PointerEventPass.PreDown,
+            PointerEventPass.PostUp,
+            PointerEventPass.PostDown
+        )
+        verifyNoMoreInteractions(customEventDispatcher)
+    }
+
+    @Test
+    fun onPointerInput_hasOrientationDownUpDown_customEventDispatchedTwiceWithDifferentLocker() {
+        filter.orientation = Orientation.Vertical
+
+        val downA = down(0)
+        val upA = downA.up(1.milliseconds)
+        val downB = down(1, 2.milliseconds)
+
+        filter::onPointerInput.invokeOverAllPasses(downA)
+
+        val locker1 = argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+
+            assertThat(allValues).hasSize(1)
+            allValues.first().scrollOrientationLocker
+        }
+
+        filter::onPointerInput.invokeOverAllPasses(upA)
+        reset(customEventDispatcher)
+        filter::onPointerInput.invokeOverAllPasses(downB)
+
+        val locker2 = argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+
+            assertThat(allValues).hasSize(1)
+            allValues.first().scrollOrientationLocker
+        }
+
+        assertThat(locker1).isNotEqualTo(locker2)
+
+        verifyNoMoreInteractions(customEventDispatcher)
+    }
+
+    // The below tests verify correct behavior in relation to scroll orientation locking.
+
+    @Test
+    fun onPointerInput_filterHorizontalPointerLockedToVertical_noStart() {
+        onPointerInput_differentOrientations(
+            Orientation.Vertical,
+            Orientation.Horizontal
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterVerticalPointerLockedToHorizontal_noStart() {
+        onPointerInput_differentOrientations(
+            Orientation.Horizontal,
+            Orientation.Vertical
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterHorizontalPointerLockedToHorizontal_start() {
+        onPointerInput_differentOrientations(
+            Orientation.Horizontal,
+            Orientation.Horizontal
+        )
+    }
+
+    @Test
+    fun onPointerInput_filterVerticalPointerLockedToVertical_start() {
+        onPointerInput_differentOrientations(
+            Orientation.Vertical,
+            Orientation.Vertical
+        )
+    }
+
+    private fun onPointerInput_differentOrientations(
+        filterOrientation: Orientation,
+        lockedOrientation: Orientation
+    ) {
+
+        // Arrange
+
+        filter.orientation = filterOrientation
+        dragStartBlocked = false
+
+        val scrollOrientationLocker = InternalScrollOrientationLocker()
+
+        filter::onCustomEvent.invokeOverAllPasses(
+            ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+        )
+
+        val down = down(0)
+        val move = down.moveBy(1.milliseconds, 3f, 5f)
+
+        filter::onPointerInput.invokeOverAllPasses(down)
+
+        scrollOrientationLocker.attemptToLockPointers(listOf(move), lockedOrientation)
+
+        // Act
+        filter::onPointerInput.invokeOverAllPasses(move)
+
+        // Assert
+        if (filterOrientation == lockedOrientation) {
+            assertThat(log.filter { it.methodName == "onStart" }).hasSize(1)
+            // onDrag get's called twice because it is called during PostUp and PostDown and nothing
+            // consumed the drag distance.
+            assertThat(log.filter { it.methodName == "onDrag" }).hasSize(2)
+        } else {
+            assertThat(log.filter { it.methodName == "onStart" }).isEmpty()
+            assertThat(log.filter { it.methodName == "onDrag" }).isEmpty()
+        }
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementIsHorizontal_locksHorizontal() {
+        onPointerInput_mayLockPointers(false, Orientation.Horizontal, 1f, 0f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsVertical_locksVertical() {
+        onPointerInput_mayLockPointers(false, Orientation.Vertical, 0f, 1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementIsBoth_locksHorizontal() {
+        onPointerInput_mayLockPointers(false, Orientation.Horizontal, -1f, -1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsBoth_locksVertical() {
+        onPointerInput_mayLockPointers(false, Orientation.Vertical, -1f, -1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementIsHorizontalBlocked_locksHorizontal() {
+        onPointerInput_mayLockPointers(true, Orientation.Horizontal, 1f, 0f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsVerticalBlocked_locksVertical() {
+        onPointerInput_mayLockPointers(true, Orientation.Vertical, 0f, 1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementIsBothBlocked_locksHorizontal() {
+        onPointerInput_mayLockPointers(true, Orientation.Horizontal, -1f, -1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsBothBlocked_locksVertical() {
+        onPointerInput_mayLockPointers(true, Orientation.Vertical, -1f, -1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsHorizontalMovementIsVertical_locksNone() {
+        onPointerInput_mayLockPointers(false, Orientation.Horizontal, 0f, -1f)
+    }
+
+    @Test
+    fun onPointerInput_filterIsVerticalMovementIsHorizontal_locksNone() {
+        onPointerInput_mayLockPointers(false, Orientation.Vertical, -1f, 0f)
+    }
+
+    private fun onPointerInput_mayLockPointers(
+        blocked: Boolean,
+        filterOrientation: Orientation,
+        dx: Float,
+        dy: Float
+    ) {
+
+        // Arrange
+
+        val otherOrientation =
+            when (filterOrientation) {
+                Orientation.Vertical -> Orientation.Horizontal
+                Orientation.Horizontal -> Orientation.Vertical
+            }
+
+        filter.orientation = filterOrientation
+
+        dragStartBlocked = blocked
+
+        val scrollOrientationLocker = InternalScrollOrientationLocker()
+
+        filter::onCustomEvent.invokeOverAllPasses(
+            ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+        )
+
+        val down = down(0)
+        val move = down.moveBy(1.milliseconds, dx, dy)
+
+        filter::onPointerInput.invokeOverAllPasses(down)
+
+        // Act
+        filter::onPointerInput.invokeOverAllPasses(move)
+
+        // Assert
+        if (!blocked && (filterOrientation == Orientation.Horizontal && dx != 0f ||
+                    filterOrientation == Orientation.Vertical && dy != 0f)
+        ) {
+            assertThat(scrollOrientationLocker.getPointersFor(listOf(move), otherOrientation))
+                .hasSize(0)
+        } else {
+            assertThat(scrollOrientationLocker.getPointersFor(listOf(move), otherOrientation))
+                .hasSize(1)
+        }
+    }
+
+    @Test
+    fun onPointerInput_Hori3Pointers1LockedVert2Average0__onStartAndOnDragNotCalled() {
+
+        // Arrange
+
+        filter.orientation = Orientation.Horizontal
+
+        val scrollOrientationLocker = InternalScrollOrientationLocker()
+        filter::onCustomEvent.invokeOverAllPasses(
+            ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+        )
+
+        val pointers = arrayOf(down(0), down(1), down(2))
+        filter::onPointerInput.invokeOverAllPasses(*pointers)
+
+        dragStartBlocked = false
+
+        // This pointer is going to be locked to vertical.
+        pointers[0] =
+            pointers[0].moveBy(
+                100.milliseconds,
+                100f,
+                0f
+            )
+        scrollOrientationLocker.attemptToLockPointers(listOf(pointers[0]), Orientation.Vertical)
+
+        // These pointers average to no movement.
+        pointers[1] =
+            pointers[1].moveBy(
+                100.milliseconds,
+                1f,
+                0f
+            )
+        pointers[2] =
+            pointers[2].moveBy(
+                100.milliseconds,
+                -1f,
+                0f
+            )
+
+        // Act
+        filter::onPointerInput.invokeOverAllPasses(*pointers)
+
+        // Assert
+        assertThat(log.filter { it.methodName == "onStart" }).isEmpty()
+        assertThat(log.filter { it.methodName == "onDrag" }).isEmpty()
+    }
+
+    @Test
+    fun onPointerInput_2Pointers1LockedInWrongOrientationOtherGoesUpThenItGoesUp_isCorrect() {
+
+        // Arrange
+
+        // Basic set up
+        filter.orientation = Orientation.Horizontal
+        dragStartBlocked = false
+        val scrollOrientationLocker = InternalScrollOrientationLocker()
+        filter::onCustomEvent.invokeOverAllPasses(
+            ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+        )
+
+        // One finger down
+        var time = 0.milliseconds
+        var pointer1 = down(0, time)
+        filter::onPointerInput.invokeOverAllPasses(pointer1)
+
+        // 2nd finger comes into play
+        time = 10.milliseconds
+        pointer1.moveTo(time)
+        var pointer2 = down(1, time)
+
+        // Lock the 2nd pointer to vertical
+        scrollOrientationLocker.attemptToLockPointers(listOf(pointer2), Orientation.Vertical)
+
+        // Dispatch 2nd finger down.
+        filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+        // Both pointers move a bunch.
+        repeat(11) {
+            time = 10.milliseconds
+            pointer1 = pointer1.moveBy(
+                10.milliseconds,
+                1f,
+                0f
+            )
+            pointer2 = pointer2.moveBy(
+                10.milliseconds,
+                1f,
+                0f
+            )
+            filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+        }
+
+        // Act 1
+
+        // Only Pointer 1 goes up
+        time = 10.milliseconds
+        pointer1 = pointer1.up(time)
+        pointer2 = pointer2.moveTo(time)
+        filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+        // Assert 1
+
+        // One pointer is still down, and even though it is locked in the other orientation, we
+        // still shouldn't stop yet.
+        assertThat(log.filter { it.methodName == "onStop" }).hasSize(0)
+
+        // Act 2
+
+        // 2nd is up
+        time = 10.milliseconds
+        pointer2 = pointer2.up(time)
+        filter::onPointerInput.invokeOverAllPasses(pointer2)
+
+        // This finger lifting should contribute no flinging since it was locked to a different
+        // orientation.
+        val loggedStops = log.filter { it.methodName == "onStop" }
+        assertThat(loggedStops).hasSize(1)
+        val velocity = loggedStops[0].pxPosition!!
+        assertThat(velocity.x).isEqualTo(0)
+        assertThat(velocity.y).isEqualTo(0)
+    }
+
+    @Test
+    fun onPointerInput_2Pointers1LockedInWrongOrientationItGoesUpThenOtherGoesUp_isCorrect() {
+
+        // Arrange
+
+        // Basic set up
+        filter.orientation = Orientation.Horizontal
+        dragStartBlocked = false
+        val scrollOrientationLocker = InternalScrollOrientationLocker()
+        filter::onCustomEvent.invokeOverAllPasses(
+            ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+        )
+
+        var time = 0.milliseconds
+
+        // One finger down
+        var pointer1 = down(0, time)
+        filter::onPointerInput.invokeOverAllPasses(pointer1)
+
+        // 2nd finger comes into play
+        time += 10.milliseconds
+        pointer1.moveTo(time)
+        var pointer2 = down(1, time)
+
+        // Lock the 2nd pointer to vertical
+        scrollOrientationLocker.attemptToLockPointers(listOf(pointer2), Orientation.Vertical)
+
+        // Dispatch 2nd finger down.
+        filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+        // Both pointers move a bunch.
+        repeat(11) {
+            time += 10.milliseconds
+            pointer1 = pointer1.moveBy(
+                10.milliseconds,
+                1f,
+                0f
+            )
+            pointer2 = pointer2.moveBy(
+                10.milliseconds,
+                1f,
+                0f
+            )
+            filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+        }
+
+        // Act 1
+
+        // Only Pointer 2 goes up
+        time += 10.milliseconds
+        pointer1 = pointer1.moveBy(
+            10.milliseconds,
+            1f,
+            0f
+        )
+        pointer2 = pointer2.up(time)
+        filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+        // Assert 1
+
+        // One pointer is still down, and even though it is locked in the other orientation, we
+        // still shouldn't stop yet.
+        assertThat(log.filter { it.methodName == "onStop" }).hasSize(0)
+
+        // Act 2
+
+        // 2nd is up
+        time += 10.milliseconds
+        pointer1 = pointer1.up(time)
+        filter::onPointerInput.invokeOverAllPasses(pointer1)
+
+        // This finger lifting should contribute no flinging since it was locked to a different
+        // orientation.
+        val loggedStops = log.filter { it.methodName == "onStop" }
+        assertThat(loggedStops).hasSize(1)
+        val velocity = loggedStops[0].pxPosition!!
+        assertThat(velocity.x).isWithin(.01f).of(100f)
+        assertThat(velocity.y).isWithin(.01f).of(0f)
+    }
+
     // Tests that verify when onCancel should not be called.
 
     @Test
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerSetupTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerSetupTest.kt
new file mode 100644
index 0000000..816dda2
--- /dev/null
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerSetupTest.kt
@@ -0,0 +1,491 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalPointerInput::class)
+
+package androidx.ui.core.gesture.scrollorientationlocking
+
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.gesture.ExperimentalPointerInput
+import androidx.ui.testutils.down
+import androidx.ui.testutils.moveTo
+import androidx.ui.testutils.up
+import androidx.ui.unit.milliseconds
+import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.argumentCaptor
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.never
+import com.nhaarman.mockitokotlin2.reset
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ScrollOrientationLockerSetupTest {
+
+    // Scenarios where dispatch does not happen.
+
+    // Valid CustomEvent, Down event, up event, all passes.
+    @Test
+    fun onPointerInput_validCustomEventThenDown_doesNotDispatchEvent() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+        scrollOrientationLocker.onCustomEventAllPasses(
+            ShareScrollOrientationLockerEvent(
+                InternalScrollOrientationLocker()
+            )
+        )
+
+        val down = down(0, 0.milliseconds)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+        verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+    }
+
+    // CustomEvent, Down then move, all passes.
+    @Test
+    fun onPointerInput_downThenMove_doesNotDispatchEvent() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val down = down(0, x = 0f, y = 0f)
+        val moveA = down.moveTo(1.milliseconds, 1f, 0f)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA))
+
+        // Assert
+        verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+    }
+
+    // CustomEvent, Down then up, all passes.
+    @Test
+    fun onPointerInput_downThenUp_doesNotDispatchEvent() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val down = down(0, x = 0f, y = 0f)
+        val up = down.up(1.milliseconds)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(up))
+
+        // Assert
+        verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+    }
+
+    // CustomEvent, Down then up, all passes.
+    @Test
+    fun onPointerInput_downThenCancel_doesNotDispatchEvent() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val down = down(0, x = 0f, y = 0f)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onCancel()
+
+        // Assert
+        verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+    }
+
+    // Scenarios where dispatch does happen.
+
+    // Down event, all passes.
+    @Test
+    fun onPointerInput_downAllPasses_dispatchesNewInternalScrollOrientationLockerOnce() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down(0)))
+
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+        verifyNoMoreInteractions(customEventDispatcher)
+    }
+
+    // Down event, InitialTunnel only.
+    @Test
+    fun onPointerInput_downInitialTunnel_dispatchesNewInternalScrollOrientationLockerOnce() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInput(listOf(down(0)), PointerEventPass.InitialDown)
+
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+        verifyNoMoreInteractions(customEventDispatcher)
+    }
+
+    // Valid CustomEvent, Down event, up event, all passes.
+    @Test
+    fun onPointerInput_invalidCustomEventThenDown_dispatchesEvent() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+        scrollOrientationLocker.onCustomEventAllPasses(
+            object : CustomEvent {}
+        )
+
+        val down = down(0, 0.milliseconds)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+    }
+
+    // Down event, followed by down event, all passes.
+    @Test
+    fun onPointerInput_downDown_dispatchesExistingScrollOrientationLockerOnce() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0, x = 0f, y = 0f)
+
+        val moveA = downA.moveTo(1.milliseconds, 0f, 0f)
+        val downB = down(1)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        var expected: InternalScrollOrientationLocker
+        argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+            expected = this.firstValue.scrollOrientationLocker
+        }
+
+        reset(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA, downB))
+        var actual: InternalScrollOrientationLocker
+        argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+            actual = this.firstValue.scrollOrientationLocker
+        }
+
+        assertThat(actual).isEqualTo(expected)
+    }
+
+    // Down event, followed by down event, InitialTunnel only.
+    @Test
+    fun onPointerInput_downDownInitialTunnel_dispatchesExistingScrollOrientationLockerOnce() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0, x = 0f, y = 0f)
+
+        val moveA = downA.moveTo(1.milliseconds, 0f, 0f)
+        val downB = down(1)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        var expected: InternalScrollOrientationLocker
+        argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+            expected = this.firstValue.scrollOrientationLocker
+        }
+
+        reset(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInput(
+            listOf(moveA, downB),
+            PointerEventPass.InitialDown
+        )
+        var actual: InternalScrollOrientationLocker
+        argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+            verify(customEventDispatcher).dispatchCustomEvent(capture())
+            actual = this.firstValue.scrollOrientationLocker
+        }
+
+        assertThat(actual).isEqualTo(expected)
+    }
+
+    // Down then up then down, all passes.
+    @Test
+    fun onPointerInput_downThenUpThenDown_dispatchesEventDuringSecondDown() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0)
+        val upA = downA.up(1.milliseconds)
+        val downB = down(1)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(upA))
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+
+        // Assert
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+    }
+
+    // Down then up then down, all passes: first internalLocker != last internalLocker
+    @Test
+    fun onPointerInput_downThenUpThenDown_firstInternalLockerNotEqualsFinalInternalLocker() {
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0, x = 0f, y = 0f)
+        val upA = downA.up(1.milliseconds)
+        val downB = down(1)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        val expected =
+            argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+                verify(customEventDispatcher).dispatchCustomEvent(capture())
+                this.firstValue.scrollOrientationLocker
+            }
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(upA))
+
+        reset(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+        val actual =
+            argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+                verify(customEventDispatcher).dispatchCustomEvent(capture())
+                this.firstValue.scrollOrientationLocker
+            }
+
+        assertThat(actual).isNotEqualTo(expected)
+    }
+
+    // Down then cancel then down, all passes.
+    @Test
+    fun onPointerInput_downThenCancelThenDown_dispatchesEventDuringSecondDown() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0)
+        val downB = down(1)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        scrollOrientationLocker.onCancel()
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+
+        // Assert
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+    }
+
+    // Down then up then down, all passes: first internalLocker != last internalLocker
+    @Test
+    fun onPointerInput_downCancelThenDown_firstInternalLockerNotEqualsFinalInternalLocker() {
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0, x = 0f, y = 0f)
+        val downB = down(1)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        val expected =
+            argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+                verify(customEventDispatcher).dispatchCustomEvent(capture())
+                this.firstValue.scrollOrientationLocker
+            }
+
+        scrollOrientationLocker.onCancel()
+        reset(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+        val actual =
+            argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+                verify(customEventDispatcher).dispatchCustomEvent(capture())
+                this.firstValue.scrollOrientationLocker
+            }
+
+        assertThat(actual).isNotEqualTo(expected)
+    }
+
+    // Valid CustomEvent, Down then up then down, all passes.
+    @Test
+    fun onPointerInput_validCustomEventDownUpDown_dispatchesEvent() {
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+        scrollOrientationLocker.onCustomEventAllPasses(
+            ShareScrollOrientationLockerEvent(
+                InternalScrollOrientationLocker()
+            )
+        )
+
+        val downA = down(0, 0.milliseconds)
+        val upA = downA.up(1.milliseconds)
+        val downB = down(1, 2.milliseconds)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(upA))
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+    }
+
+    // CustomEvent, Down then move then down, all passes.
+    @Test
+    fun onPointerInput_downThenMoveThenDown_doesDispatchesEvent() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0, 0.milliseconds, x = 0f, y = 0f)
+
+        val moveA1 = downA.moveTo(1.milliseconds, 1f, 0f)
+
+        val moveA2 = moveA1.moveTo(2.milliseconds, 1f, 0f)
+        val downB = down(0, 2.milliseconds, x = 0f, y = 0f)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA1))
+
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA2, downB))
+
+        // Assert
+        verify(customEventDispatcher).dispatchCustomEvent(any())
+    }
+
+    // CustomEvent, Down then move then down, all passes.
+    @Test
+    fun onPointerInput_downThenMoveThenDown_firstInternalLockerMatchesSecondInternalLocker() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        val downA = down(0, 0.milliseconds, x = 0f, y = 0f)
+
+        val moveA1 = downA.moveTo(1.milliseconds, 1f, 0f)
+
+        val moveA2 = moveA1.moveTo(2.milliseconds, 1f, 0f)
+        val downB = down(0, 2.milliseconds, x = 0f, y = 0f)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+        val expected =
+            argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+                verify(customEventDispatcher).dispatchCustomEvent(capture())
+                this.firstValue.scrollOrientationLocker
+            }
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA1))
+
+        reset(customEventDispatcher)
+
+        // Act
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA2, downB))
+        val actual =
+            argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+                verify(customEventDispatcher).dispatchCustomEvent(capture())
+                this.firstValue.scrollOrientationLocker
+            }
+
+        // Assert
+        assertThat(actual).isEqualTo(expected)
+    }
+
+    // Verification of situations when exceptions should be thrown.
+
+    @Test(expected = IllegalStateException::class)
+    fun attemptToLockPointers_notInitialized_illegalStateExceptionThrown() {
+        val customEventDispatcher = mock<CustomEventDispatcher>()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        scrollOrientationLocker.attemptToLockPointers(listOf(down(0)), Orientation.Vertical)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun getPointersFor_notInitialized_illegalStateExceptionThrown() {
+        val customEventDispatcher = mock<CustomEventDispatcher>()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        scrollOrientationLocker.getPointersFor(listOf(down(0)), Orientation.Vertical)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun onCustomEvent_isLockerOWner_illegalStateExceptionThrown() {
+        val customEventDispatcher = mock<CustomEventDispatcher>()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+        scrollOrientationLocker.onPointerInputAllPasses(listOf(down(0)))
+
+        scrollOrientationLocker.onCustomEventAllPasses(
+            ShareScrollOrientationLockerEvent(
+                InternalScrollOrientationLocker()
+            )
+        )
+    }
+}
+
+private fun ScrollOrientationLocker.onPointerInputAllPasses(
+    changes: List<PointerInputChange>
+) {
+    PointerEventPass.values().forEach {
+        onPointerInputSetup(changes, it)
+        onPointerInputTearDown(changes, it)
+    }
+}
+
+private fun ScrollOrientationLocker.onPointerInput(
+    changes: List<PointerInputChange>,
+    pass: PointerEventPass
+) {
+    onPointerInputSetup(changes, pass)
+    onPointerInputTearDown(changes, pass)
+}
+
+private fun ScrollOrientationLocker.onCustomEventAllPasses(
+    event: CustomEvent
+) {
+    PointerEventPass.values().forEach {
+        onCustomEvent(event, it)
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerTest.kt
new file mode 100644
index 0000000..8e304c9
--- /dev/null
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerTest.kt
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalPointerInput::class)
+
+package androidx.ui.core.gesture.scrollorientationlocking
+
+import androidx.ui.core.CustomEventDispatcher
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.gesture.ExperimentalPointerInput
+import androidx.ui.testutils.down
+import androidx.ui.unit.milliseconds
+import com.google.common.truth.Truth
+import com.nhaarman.mockitokotlin2.mock
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+val c1 = down(1, 0.milliseconds, x = 1f, y = 1f)
+val c2 = down(2, 0.milliseconds, x = 2f, y = 2f)
+
+class LockingConfig(
+    val changes: List<PointerInputChange>,
+    val orientation: Orientation
+)
+
+@RunWith(Parameterized::class)
+class ScrollOrientationLockerTest(
+    private val lockingConfigs: List<LockingConfig>,
+    private val inputChanges: List<PointerInputChange>,
+    private val inputOrientation: Orientation,
+    private val expectedOutput: List<PointerInputChange>
+) {
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(
+            name = "lockedConfigs = {0}, " +
+                    "inputChanges = {1}, " +
+                    "inputOrientation = {2}, " +
+                    "expectedOutput = {3}"
+        )
+        fun parameters(): List<Array<Any?>> {
+
+            val configs = mutableListOf<Array<Any?>>()
+
+            val allPointerCombinations = listOf(
+                listOf(),
+                listOf(c1),
+                listOf(c2),
+                listOf(c1, c2)
+            )
+
+            val pointerCombinationsWith2 =
+                listOf(
+                    listOf(c2),
+                    listOf(c1, c2)
+                )
+
+            // If the requested orientation and the locked orientation is the same, whatever is
+            // requested is returned.
+            allPointerCombinations.forEach { locked ->
+                allPointerCombinations.forEach { input ->
+                    Orientation.values().forEach { orientation ->
+                        configs.add(
+                            arrayOf(
+                                listOf(
+                                    LockingConfig(locked, orientation)
+                                ),
+                                input,
+                                orientation,
+                                input
+                            )
+                        )
+                    }
+                }
+            }
+
+            // If pointer 1 is locked in orientation A, all requests with sets that include
+            // pointer 2 and in orientation B will result in the set that just includes pointer 2.
+            pointerCombinationsWith2.forEach { input ->
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1), Orientation.Horizontal)
+                        ),
+                        input,
+                        Orientation.Vertical,
+                        listOf(c2)
+                    )
+                )
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1), Orientation.Vertical)
+                        ),
+                        input,
+                        Orientation.Horizontal,
+                        listOf(c2)
+                    )
+                )
+            }
+
+            // If pointer 1 is locked in orientation A, and pointer 2 is locked in orientation B,
+            // all requests with sets that include pointer 2 and with orientation B will result in
+            // the set that just includes Pointer 2.
+            pointerCombinationsWith2.forEach { input ->
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1), Orientation.Horizontal),
+                            LockingConfig(listOf(c2), Orientation.Vertical)
+                        ),
+                        input,
+                        Orientation.Vertical,
+                        listOf(c2)
+                    )
+                )
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1), Orientation.Vertical),
+                            LockingConfig(listOf(c2), Orientation.Horizontal)
+                        ),
+                        input,
+                        Orientation.Horizontal,
+                        listOf(c2)
+                    )
+                )
+            }
+
+            // If all of the changes are locked to one orientation, no matter what is requested
+            // in the other, no changes will be returned.
+            allPointerCombinations.forEach { input ->
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1, c2), Orientation.Horizontal)
+                        ),
+                        input,
+                        Orientation.Vertical,
+                        listOf<PointerInputChange>()
+                    )
+                )
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1, c2), Orientation.Vertical)
+                        ),
+                        input,
+                        Orientation.Horizontal,
+                        listOf<PointerInputChange>()
+                    )
+                )
+            }
+
+            // If pointer 1 is locked in orientation A, and then is attempted to be locked in
+            // orientation B, all requests with sets that include pointer 2 and in orientation B
+            // will result in the set that just includes pointer 2.
+            pointerCombinationsWith2.forEach { input ->
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1), Orientation.Horizontal),
+                            LockingConfig(listOf(c1), Orientation.Vertical)
+                        ),
+                        input,
+                        Orientation.Vertical,
+                        listOf(c2)
+                    )
+                )
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1), Orientation.Vertical),
+                            LockingConfig(listOf(c1), Orientation.Horizontal)
+                        ),
+                        input,
+                        Orientation.Horizontal,
+                        listOf(c2)
+                    )
+                )
+            }
+
+            // If all of the changes are locked to orientation A, and then are attempted to be
+            // locked in brientation B , no matter what is requested in orientation B, no changes
+            // will be returned.
+            allPointerCombinations.forEach { input ->
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1, c2), Orientation.Horizontal),
+                            LockingConfig(listOf(c1, c2), Orientation.Vertical)
+                        ),
+                        input,
+                        Orientation.Vertical,
+                        listOf<PointerInputChange>()
+                    )
+                )
+                configs.add(
+                    arrayOf(
+                        listOf(
+                            LockingConfig(listOf(c1, c2), Orientation.Vertical),
+                            LockingConfig(listOf(c1, c2), Orientation.Horizontal)
+
+                        ),
+                        input,
+                        Orientation.Horizontal,
+                        listOf<PointerInputChange>()
+                    )
+                )
+            }
+
+            return configs
+        }
+    }
+
+    @Test
+    fun test() {
+
+        // Arrange
+
+        val customEventDispatcher: CustomEventDispatcher = mock()
+        val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+        scrollOrientationLocker.onPointerInputSetup(inputChanges, PointerEventPass.InitialDown)
+        lockingConfigs.forEach {
+            scrollOrientationLocker.attemptToLockPointers(it.changes, it.orientation)
+        }
+
+        // Act
+        val actual = scrollOrientationLocker.getPointersFor(inputChanges, inputOrientation)
+
+        // Assert
+        Truth.assertThat(expectedOutput).isEqualTo(actual)
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt
index 57c608b..a019b63 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt
@@ -17,6 +17,7 @@
 package androidx.ui.core.selection
 
 import androidx.compose.frames.commit
+import androidx.compose.frames.inFrame
 import androidx.compose.frames.open
 import androidx.test.filters.SmallTest
 import androidx.ui.core.LayoutCoordinates
@@ -82,7 +83,7 @@
 
     @Before
     fun setup() {
-        open(false) // we open a Frame so state reads are allowed
+        if (!inFrame) open(false) // we open a Frame so state reads are allowed
 
         selectionRegistrar.subscribe(selectable)
 
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
index 6fc39b6..a3bd118 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
@@ -17,6 +17,7 @@
 package androidx.ui.core.selection
 
 import androidx.compose.frames.commit
+import androidx.compose.frames.inFrame
 import androidx.compose.frames.open
 import androidx.test.filters.SmallTest
 import androidx.ui.core.LayoutCoordinates
@@ -79,7 +80,7 @@
 
     @Before
     fun setup() {
-        open(false) // we open a Frame so state reads are allowed
+        if (!inFrame) open(false) // we open a Frame so state reads are allowed
         val containerLayoutCoordinates = mock<LayoutCoordinates> {
             on { isAttached } doReturn true
         }
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt
index b6888ed..10d0605 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt
@@ -17,6 +17,7 @@
 package androidx.ui.core.selection
 
 import androidx.compose.frames.commit
+import androidx.compose.frames.inFrame
 import androidx.compose.frames.open
 import androidx.test.filters.SmallTest
 import androidx.ui.core.LayoutCoordinates
@@ -83,7 +84,7 @@
 
     @Before
     fun setup() {
-        open(false) // we open a Frame so state reads are allowed
+        if (!inFrame) open(false) // we open a Frame so state reads are allowed
         selectionRegistrar.subscribe(selectable)
         selectionManager.containerLayoutCoordinates = containerLayoutCoordinates
         selectionManager.hapticFeedBack = hapticFeedback
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt
index 05917ff..cb4e62ad 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt
@@ -18,4 +18,10 @@
 
 class Matrix() {
     fun isIdentity() = true
+
+    fun reset() {
+    }
+
+    fun setTranslate(dx: Float, dy: Float) {
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
index 42216bb..9a22979 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
@@ -53,4 +53,10 @@
     }
 
     fun isConvex(): Boolean = skijaPath.isConvex
-}
\ No newline at end of file
+    fun addPath(src: Path, dx: Float, dy: Float) {
+        skijaPath.addPath(src.skijaPath, dx, dy)
+    }
+
+    fun transform(matrix: Matrix) {
+    }
+}
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 25a05ac..a9d9b12 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
@@ -19,6 +19,7 @@
 import javax.swing.SwingUtilities
 
 public class Handler() {
+    constructor(looper: Looper) : this()
     constructor(looper: Looper, callback: Handler.Callback) : this()
 
     constructor(looper: Looper, callback: Callback, async: Boolean) : this()
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
index 1b530d4..2b8e02b 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
@@ -79,8 +79,6 @@
 
     open fun onLayout (changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {}
 
-    open fun onAttachedToWindow() {}
-
     open fun dispatchDraw(canvas: Canvas) {}
 
     open fun dispatchTouchEvent(event: MotionEvent): Boolean = true
@@ -148,6 +146,10 @@
 
     var mRecreateDisplayList: Boolean = false
 
+    var isAttachedToWindow = false
+
+    var isLayoutRequested = false
+
     fun layout(left: Int, top: Int, right: Int, bottom: Int) {
         this.left = left
         this.top = top
@@ -181,4 +183,8 @@
             bottom += offset
         }
     }
+
+    open fun onAttachedToWindow() {
+        isAttachedToWindow = true
+    }
 }
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
index 585f962..7d30c7d 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
@@ -26,7 +26,8 @@
 abstract class ViewGroup(context: Context) : View(context), ViewParent {
     var clipChildren: Boolean = true
     var children = mutableListOf<View>()
-    val childCount = children.count()
+    val childCount: Int
+        get() = children.count()
 
     fun getChildAt(i: Int) = children[i]
 
@@ -48,6 +49,13 @@
         children.add(child)
     }
 
+    override fun onAttachedToWindow() {
+        super.onAttachedToWindow()
+        children.forEach {
+            it.onAttachedToWindow()
+        }
+    }
+
     override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
 
     fun drawChild(canvas: Canvas, view: View, drawingTime: Long): Boolean {
diff --git a/ui/ui-desktop/build.gradle b/ui/ui-desktop/build.gradle
index 2d31f7d..05ecc18 100644
--- a/ui/ui-desktop/build.gradle
+++ b/ui/ui-desktop/build.gradle
@@ -51,7 +51,7 @@
 
 repositories {
     // To allow using local Skija build.
-    mavenLocal()
+    // mavenLocal()
 }
 
 configurations {
@@ -84,14 +84,10 @@
     ui_components "org.jogamp.gluegen:gluegen-rt-natives-macosx-universal:2.4.0-rc-20200306"
 
     compose_compiler_jar project(":compose:compose-compiler")
-}
 
-dependencies {
     kotlinPlugin project(path: ":compose:compose-compiler")
 }
 
-def joglDir = "${project.rootDir}/ui-desktop/libs"
-def androidxDir = "${project.rootDir}/ui-desktop/libs"
 def composeClassDir = project.rootDir.absolutePath + "/ui-desktop/compose-libs/"
 
 kotlin {
@@ -100,9 +96,8 @@
     sourceSets {
         commonMain.dependencies {
             api(KOTLIN_STDLIB_COMMON)
-            implementation project(":compose:compose-runtime")
+            api project(":compose:compose-runtime")
         }
-        
 
         jvmMain {
             resources.srcDirs += new File(SupportConfigKt.getExternalProjectPath(project), "noto-fonts/other/")
@@ -110,30 +105,28 @@
 
         jvmMain.dependencies {
             api(KOTLIN_STDLIB)
+            api(KOTLIN_STDLIB_JDK8)
             api(KOTLIN_COROUTINES_CORE)
 
             api "org.jetbrains.skija:skija:0.2.41"
 
             api project(":ui:ui-desktop:android-emu")
 
-            api files("$joglDir/gluegen-rt.jar")
-            api files("$joglDir/jogl-all.jar")
-
-            api fileTree(project.rootDir.absolutePath + "/ui-desktop/compose-libs")
+            api fileTree(composeClassDir)
 
             implementation(KOTLIN_COROUTINES_SWING)
-            implementation files("$androidxDir/core-common-2.1.0.jar")
             implementation "androidx.lifecycle:lifecycle-common:2.3.0-alpha01"
             implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
 
-            implementation files("$joglDir/gluegen-rt-natives-macosx-universal.jar")
-            implementation files("$joglDir/jogl-all-natives-macosx-universal.jar")
-
             // TODO: this is a bit ugly. We introduce dependency here, but in fact
             // manually copy it later, as run task will have .aar in the classpath.
             implementation "androidx.core:core:1.0.0"
             implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
         }
+
+        jvmTest.dependencies {
+            implementation(JUNIT)
+        }
     }
 }
 
@@ -200,7 +193,6 @@
     fis.close()
 }
 
-
 // Find in dependencies first (BFS) task's output ending with `name`.
 String findInDeps(Task root, Closure<Boolean> matcher) {
     // Do BFS by deps.
@@ -241,7 +233,60 @@
     fs.close()
 }
 
-task extractJars {
+project.tasks.register("extractJars").configure {
+    inputs.files(project.provider {
+        def result = []
+        uiComponents.each { component ->
+            def depProject = project(":ui:" + component)
+            def task = depProject.tasks.named("assemble").get()
+            def srcJar = findInDeps(task, { absolutePath ->
+                absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+            })
+            result.add(file(srcJar))
+        }
+        configurations.ui_components.getIncoming().artifactView(
+                { config ->
+                    config.attributes({container ->
+                        // ... container.attribute(Attribute.of("artifactType", String.class), "android-classes")
+                    })
+                })
+                .getArtifacts().getArtifactFiles().each { component ->
+                    result.add(component)
+                }
+        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")
+        result.add(file(runtimeJar))
+
+        return result
+    })
+
+    outputs.files(project.provider {
+        def result = [fileTree(dir: composeClassDir, include: [])]
+        uiComponents.each { component ->
+            def depProject = project(":ui:" + component)
+            def task = depProject.tasks.named("assemble").get()
+            def srcJar = findInDeps(task, { absolutePath ->
+                absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+            })
+            result.add(file(composeClassDir + component + ".jar"))
+        }
+        configurations.ui_components.getIncoming().artifactView(
+                { config ->
+                    config.attributes({container ->
+                        // ... container.attribute(Attribute.of("artifactType", String.class), "android-classes")
+                    })
+                })
+                .getArtifacts().getArtifactFiles().each { component ->
+                    result.add(file(composeClassDir + component.name))
+                }
+        return result
+    })
+
     doLast {
         // Find all JAR files matching components.
         file(composeClassDir).mkdir()
@@ -258,24 +303,6 @@
                 makeLinkOrCopy(srcJar, destJar)
             }
         }
-        // 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 ->
-            println(absolutePath)
-            Pattern.matches(".*/jarjar/compose-compiler.jar", absolutePath)
-        })
-        if (compilerJar == null)
-            throw new Error("cannot find compose-compiler.jar")
-        makeLinkOrCopy(compilerJar, composeClassDir + "compose-compiler.jar")
-        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")
-        makeLinkOrCopy(runtimeJar, composeClassDir + "compose-runtime.jar")
 
         configurations.ui_components.getIncoming().artifactView(
                 { config ->
@@ -304,13 +331,25 @@
         useIR = true
     }
 }
-
-task desktopJar(type: Jar) {
+project.tasks.register("jar", Jar).configure {
     baseName = "ui-desktop"
     from { kotlin.jvm().compilations["main"].output.allOutputs }
     destinationDir file(composeClassDir)
 }
 
+project.tasks.register("test", JavaExec).configure {
+    dependsOn(":ui:ui-desktop:jar")
+    main = 'androidx.ui.desktop.RunnerKt'
+    def compilation = kotlin.jvm().compilations["test"]
+    classpath =
+        compilation.output.allOutputs +
+        compilation.runtimeDependencyFiles +
+        fileTree(composeClassDir)
+}
+
 clean.doFirst {
     delete composeClassDir
-}
\ No newline at end of file
+}
+
+// TODO(igotti): figure out buildbots breakage.
+// rootProject.tasks.getByName("buildOnServer").dependsOn(project.path + ":jar")
\ No newline at end of file
diff --git a/ui/ui-desktop/samples/build.gradle b/ui/ui-desktop/samples/build.gradle
index 675bf8d..becec20 100644
--- a/ui/ui-desktop/samples/build.gradle
+++ b/ui/ui-desktop/samples/build.gradle
@@ -35,7 +35,7 @@
         jvmMain {
             resources.srcDirs += "src/jvmMain/res"
         }
-        
+
         jvmMain.dependencies {
             implementation project(":ui:ui-desktop")
             implementation fileTree(sdkDir)
@@ -50,7 +50,7 @@
 }
 
 task run1(type: JavaExec) {
-    dependsOn(":ui:ui-desktop:desktopJar")
+    dependsOn(":ui:ui-desktop:jar")
     main = 'androidx.ui.desktop.examples.example1.MainKt'
     def compilation = kotlin.jvm().compilations["main"]
     classpath =
@@ -60,7 +60,7 @@
 }
 
 task run2(type: JavaExec) {
-    dependsOn(":ui:ui-desktop:desktopJar")
+    dependsOn(":ui:ui-desktop:jar")
     main = 'androidx.ui.desktop.examples.example2.MainKt'
     def compilation = kotlin.jvm().compilations["main"]
     classpath =
diff --git a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
index 8e8a28e..d9eb5cf 100644
--- a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
+++ b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
@@ -17,21 +17,23 @@
 
 import android.graphics.Bitmap
 import androidx.compose.Composable
+import androidx.compose.remember
 import androidx.compose.state
 import androidx.compose.remember
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
-import androidx.ui.graphics.Color
+import androidx.ui.desktop.examples.mainWith
 import androidx.ui.foundation.Image
 import androidx.ui.foundation.Text
 import androidx.ui.foundation.drawBackground
-import androidx.ui.graphics.asImageAsset
+import androidx.ui.graphics.Color
 import androidx.ui.graphics.ImageAsset
+import androidx.ui.graphics.asImageAsset
 import androidx.ui.layout.Arrangement
 import androidx.ui.layout.Column
 import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.wrapContentSize
 import androidx.ui.layout.preferredHeight
+import androidx.ui.layout.wrapContentSize
 import androidx.ui.material.Button
 import androidx.ui.material.CircularProgressIndicator
 import androidx.ui.material.ExtendedFloatingActionButton
@@ -39,12 +41,18 @@
 import androidx.ui.material.Scaffold
 import androidx.ui.material.Slider
 import androidx.ui.material.TopAppBar
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.SpanStyle
 import androidx.ui.unit.dp
-
-import androidx.ui.desktop.examples.mainWith
+import androidx.ui.unit.sp
+import androidx.ui.text.font.fontFamily
+import androidx.ui.desktop.font
+import androidx.ui.layout.padding
 
 private const val title = "Desktop Compose Elements"
 
+val italicFont = fontFamily(font("Noto Italic", "NotoSans-Italic.ttf"))
+
 fun main() = mainWith(title) @Composable {
     Scaffold(
         topBar = {
@@ -72,6 +80,46 @@
                         .preferredHeight(56.dp)
                         .wrapContentSize(Alignment.Center)
                 )
+
+                Text(
+                    text = with(AnnotatedString.Builder("The quick ")) {
+                        pushStyle(SpanStyle(color = Color(0xff964B00)))
+                        append("brown fox")
+                        pop()
+                        append(" 🦊 ate a ")
+                        pushStyle(SpanStyle(fontSize = 30.sp))
+                        append("zesty hamburgerfons")
+                        pop()
+                        append(" 🍔.\nThe 👩‍👩‍👧‍👧 laughed.")
+                        addStyle(SpanStyle(color = Color.Green), 25, 35)
+                        toAnnotatedString()
+                    },
+                    color = Color.Black
+                )
+
+                Text(
+                    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. Excepteur" +
+                    " sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt" +
+                    " mollit anim id est laborum."
+                )
+
+                Text(
+                    text = "fun <T : Comparable<T>> List<T>.quickSort(): List<T> = when {\n" +
+                    "  size < 2 -> this\n" +
+                    "  else -> {\n" +
+                    "    val pivot = first()\n" +
+                    "    val (smaller, greater) = drop(1).partition { it <= pivot }\n" +
+                    "    smaller.quickSort() + pivot + greater.quickSort()\n" +
+                    "   }\n" +
+                    "}",
+                    modifier = Modifier.padding(10.dp),
+                    fontFamily = italicFont
+                )
+
                 Button(onClick = {
                     amount.value++
                 }) {
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
index 64b13cd..7d2298a 100644
--- 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
@@ -20,7 +20,6 @@
 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
@@ -37,9 +36,9 @@
         drawRect(Color.Magenta)
         inset(10.0f) {
             drawLine(
-                p1 = Offset.Zero,
-                p2 = Offset(size.width, size.height),
-                stroke = Stroke(width = 5.0f),
+                start = Offset.Zero,
+                end = Offset(size.width, size.height),
+                strokeWidth = 5.0f,
                 color = Color.Red
             )
         }
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopFont.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopFont.kt
new file mode 100644
index 0000000..ef68021a
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopFont.kt
@@ -0,0 +1,98 @@
+/*
+* 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
+
+import org.jetbrains.skija.SkTypeface
+import androidx.ui.text.font.Font as uiFont
+import androidx.ui.text.font.FontWeight
+import androidx.ui.text.font.FontStyle
+import androidx.ui.text.font.FontFamily
+import androidx.ui.text.font.FontListFontFamily
+import org.jetbrains.skija.FontCollection
+import org.jetbrains.skija.FontManager
+import org.jetbrains.skija.TypefaceFontProvider
+import java.nio.file.Files
+import java.nio.file.StandardCopyOption
+import java.io.File
+
+data class Font(
+    val alias: String,
+    val path: String,
+    override val weight: FontWeight = FontWeight.Normal,
+    override val style: FontStyle = FontStyle.Normal
+) : uiFont
+
+fun font(
+    alias: String,
+    path: String,
+    weight: FontWeight = FontWeight.Normal,
+    style: FontStyle = FontStyle.Normal
+): Font = Font(alias, path, weight, style)
+
+class FontLoader() : uiFont.ResourceLoader {
+    val fonts = FontCollection()
+    private val fontProvider = TypefaceFontProvider()
+
+    init {
+        fonts.setDefaultFontManager(FontManager.getDefault())
+        fonts.setAssetFontManager(fontProvider)
+    }
+
+    fun ensureRegistered(fontFamily: FontFamily): List<String> =
+        when (fontFamily) {
+            is FontListFontFamily -> fontFamily.fonts.map { load(it) }
+            FontFamily.Default -> listOf()
+            else -> throw IllegalArgumentException("Unknown font family type: $fontFamily")
+        }
+
+    private val registered = mutableSetOf<String>()
+    override fun load(font: uiFont): String {
+        when (font) {
+            is Font -> {
+                synchronized(this) {
+                    if (!registered.contains(font.alias)) {
+                        val typeface = typefaceResource(font.path)
+                        fontProvider.registerTypeface(typeface, font.alias)
+                        registered.add(font.alias)
+                    }
+                }
+                return font.alias
+            }
+            else -> throw IllegalArgumentException("Unknown font type: $font")
+        }
+    }
+}
+
+// TODO: get fontFamily from loaded typeface via SkTypeface.getFamilyName
+private fun typefaceResource(resourcePath: String): SkTypeface {
+    val path = getFontPathAsString(resourcePath)
+    return SkTypeface.makeFromFile(path, 0)
+}
+
+// TODO: add to skija an ability to load typefaces from memory
+fun getFontPathAsString(resourcePath: String): String {
+    val tempDir = File(System.getProperty("java.io.tmpdir"), "compose").apply {
+        mkdirs()
+        deleteOnExit()
+    }
+    val tempFile = File(tempDir, resourcePath).apply {
+        deleteOnExit()
+    }
+    val stream = Thread.currentThread().contextClassLoader.getResourceAsStream(resourcePath)
+    if (stream == null) throw Error("Cannot find font $resourcePath")
+    Files.copy(stream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
+    return tempFile.absolutePath
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraph.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraph.kt
new file mode 100644
index 0000000..610b4ac
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraph.kt
@@ -0,0 +1,175 @@
+/*
+ * 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
+
+import androidx.ui.geometry.Rect
+import androidx.ui.graphics.Canvas
+import androidx.ui.graphics.Path
+import androidx.ui.graphics.AndroidPath
+import androidx.ui.text.Paragraph
+import androidx.ui.text.ParagraphConstraints
+import androidx.ui.text.ParagraphIntrinsics
+import androidx.ui.text.TextRange
+import androidx.ui.text.style.TextDirection
+import androidx.ui.geometry.Offset
+import org.jetbrains.skija.Paragraph as SkParagraph
+
+internal class DesktopParagraph(
+    intrinsics: ParagraphIntrinsics,
+    val maxLines: Int,
+    val ellipsis: Boolean,
+    val constraints: ParagraphConstraints
+) : Paragraph {
+
+    val paragraphIntrinsics = intrinsics as DesktopParagraphIntrinsics
+
+    val para = paragraphIntrinsics.para
+
+    init {
+        para.layout(constraints.width)
+    }
+
+    override val width: Float
+        get() = para.getMaxWidth()
+
+    override val height: Float
+        get() = para.getHeight()
+
+    override val minIntrinsicWidth: Float
+        get() = paragraphIntrinsics.minIntrinsicWidth
+
+    override val maxIntrinsicWidth: Float
+        get() = paragraphIntrinsics.maxIntrinsicWidth
+
+    override val firstBaseline: Float
+        get() = para.getLineMetrics().first().baseline.toFloat()
+
+    override val lastBaseline: Float
+        get() = para.getLineMetrics().last().baseline.toFloat()
+
+    override val didExceedMaxLines: Boolean
+        // TODO: support text ellipsize.
+        get() = para.lineNumber() < maxLines
+
+    override val lineCount: Int
+        get() = para.lineNumber().toInt()
+
+    override val placeholderRects: List<Rect?> get() {
+        println("Paragraph.placeholderRects")
+        return listOf()
+    }
+
+    override fun getPathForRange(start: Int, end: Int): Path {
+        val boxes = para.getRectsForRange(
+            start,
+            end,
+            SkParagraph.RectHeightStyle.MAX,
+            SkParagraph.RectWidthStyle.MAX
+        )
+        val path = Path() as AndroidPath
+        for (b in boxes) {
+            path.internalPath.skijaPath.addRect(b.rect)
+        }
+        return path
+    }
+
+    override fun getCursorRect(offset: Int): Rect {
+        println("Paragraph.getCursorRect $offset")
+        return Rect(0.0f, 0.0f, 0.0f, 0.0f)
+    }
+
+    override fun getLineLeft(lineIndex: Int): Float {
+        println("Paragraph.getLineLeft $lineIndex")
+        return 0.0f
+    }
+
+    override fun getLineRight(lineIndex: Int): Float {
+        println("Paragraph.getLineRight $lineIndex")
+        return 0.0f
+    }
+
+    override fun getLineTop(lineIndex: Int): Float {
+        println("Paragraph.getLineTop $lineIndex")
+        return 0.0f
+    }
+
+    override fun getLineBottom(lineIndex: Int): Float {
+        println("Paragraph.getLineBottom $lineIndex")
+        return 0.0f
+    }
+
+    override fun getLineHeight(lineIndex: Int): Float {
+        println("Paragraph.getLineHeight $lineIndex")
+        return 0.0f
+    }
+
+    override fun getLineWidth(lineIndex: Int): Float {
+        println("Paragraph.getLineWidth $lineIndex")
+        return 0.0f
+    }
+
+    override fun getLineStart(lineIndex: Int): Int {
+        println("Paragraph.getLineStart $lineIndex")
+        return 0
+    }
+
+    override fun getLineEnd(lineIndex: Int): Int {
+        println("Paragraph.getLineEnd $lineIndex")
+        return 0
+    }
+
+    override fun getLineEllipsisOffset(lineIndex: Int): Int {
+        println("Paragraph.getLineEllipsisOffset $lineIndex")
+        return 0
+    }
+
+    override fun getLineEllipsisCount(lineIndex: Int): Int {
+        println("Paragraph.getLineEllipsisCount $lineIndex")
+        return 0
+    }
+
+    override fun getLineForOffset(offset: Int): Int {
+        println("Paragraph.getLineForOffset $offset")
+        return 0
+    }
+
+    override fun getHorizontalPosition(offset: Int, usePrimaryDirection: Boolean): Float {
+        println("getHorizontalPosition $offset, $usePrimaryDirection")
+        return 0.0f
+    }
+
+    override fun getParagraphDirection(offset: Int): TextDirection = TextDirection.Ltr
+
+    override fun getBidiRunDirection(offset: Int): TextDirection = TextDirection.Ltr
+
+    override fun getOffsetForPosition(position: Offset): Int {
+        return para.getGlyphPositionAtCoordinate(position.x, position.y).position
+    }
+
+    override fun getBoundingBox(offset: Int): Rect {
+        println("getBoundingBox $offset")
+        return Rect(0.0f, 0.0f, 0.0f, 0.0f)
+    }
+
+    override fun getWordBoundary(offset: Int): TextRange {
+        println("getWordBoundary $offset")
+        return TextRange(0, 0)
+    }
+
+    override fun paint(canvas: Canvas) {
+        para.paint(canvas.nativeCanvas.skijaCanvas, 0.0f, 0.0f)
+    }
+}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraphIntrinsics.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraphIntrinsics.kt
new file mode 100644
index 0000000..2354d0d
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraphIntrinsics.kt
@@ -0,0 +1,159 @@
+/*
+* 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
+
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.toArgb
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.ParagraphIntrinsics
+import androidx.ui.text.Placeholder
+import androidx.ui.text.SpanStyle
+import androidx.ui.text.SpanStyleRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.font.Font
+import androidx.ui.unit.Density
+import androidx.ui.unit.TextUnit
+import kotlin.math.ceil
+import org.jetbrains.skija.Paragraph
+import org.jetbrains.skija.ParagraphBuilder
+import org.jetbrains.skija.ParagraphStyle
+import org.jetbrains.skija.TextStyle as SkTextStyle
+
+internal class DesktopParagraphIntrinsics(
+    val text: String,
+    style: TextStyle,
+    spanStyles: List<SpanStyleRange>,
+    @Suppress("UNUSED_PARAMETER") placeholders: List<AnnotatedString.Range<Placeholder>>,
+    @Suppress("UNUSED_PARAMETER") density: Density,
+    resourceLoader: Font.ResourceLoader
+) : ParagraphIntrinsics {
+
+    val fontLoader = resourceLoader as FontLoader
+    val para: Paragraph
+    init {
+        para = buildParagraph(text, style, spanStyles)
+
+        para.layout(Float.POSITIVE_INFINITY)
+    }
+
+    override val minIntrinsicWidth = ceil(para.getMinIntrinsicWidth())
+    override val maxIntrinsicWidth = ceil(para.getMaxIntrinsicWidth())
+
+    /**
+     * SkParagraph styles model doesn't match Compose's one.
+     * SkParagraph has only a stack-based push/pop styles interface that works great with Span
+     * trees.
+     * But in Compose we have a list of SpanStyles attached to arbitrary ranges, possibly
+     * overlapped, where a position in the list denotes style's priority
+     * We map Compose styles to SkParagraph styles by projecting every range start/end to single
+     * positions line and maintaining a list of active styles while building a paragraph. This list
+     * of active styles is being compiled into single SkParagraph's style for every chunk of text
+    */
+    private fun buildParagraph(
+        text: String,
+        textStyle: TextStyle,
+        spanStyles: List<SpanStyleRange>
+    ): Paragraph {
+        val cuts = spansToCuts(spanStyles)
+
+        var pos = 0
+        val ps = textStyleToParagraphStyle(textStyle)
+        val pb = ParagraphBuilder(ps, fontLoader.fonts)
+        // TODO: for some reasons paragraph style doesn't apply to text. maybe it's Skia bug,
+        // we need to investigate
+        val currentStyles = mutableListOf(Pair(0, textStyle.toSpanStyle()))
+        pb.pushStyle(textStylesToSkStyle(currentStyles)!!)
+
+        for (cut in cuts) {
+            pb.addText(text.subSequence(pos, cut.position).toString())
+            pb.popStyle()
+
+            when (cut.instruction) {
+                StyleInstruction.ADD -> currentStyles.add(Pair(cut.priority, cut.style))
+                StyleInstruction.REMOVE -> currentStyles.remove(Pair(cut.priority, cut.style))
+            }
+
+            textStylesToSkStyle(currentStyles)?.let { ts ->
+                pb.pushStyle(ts)
+            }
+            pos = cut.position
+        }
+
+        pb.addText(text.subSequence(pos, text.length).toString())
+
+        return pb.build()
+    }
+
+    private enum class StyleInstruction {
+        ADD,
+        REMOVE
+    }
+
+    private data class Cut(
+        val position: Int,
+        val priority: Int,
+        val style: SpanStyle,
+        val instruction: StyleInstruction
+    )
+
+    private fun spansToCuts(spans: List<SpanStyleRange>): List<Cut> {
+        val positions = mutableMapOf<Int, Cut>()
+        for ((i, span) in spans.withIndex()) {
+            positions[span.start] = Cut(span.start, i, span.item, StyleInstruction.ADD)
+            positions[span.end] = Cut(span.end, i, span.item, StyleInstruction.REMOVE)
+        }
+
+        val cuts = ArrayList<Cut>(positions.size)
+
+        for (v in positions.toSortedMap().values) {
+            cuts.add(v)
+        }
+        return cuts
+    }
+
+    private fun textStyleToParagraphStyle(style: TextStyle): ParagraphStyle {
+        val pStyle = ParagraphStyle()
+        val textStyle = SkTextStyle()
+        applyStyles(style.toSpanStyle(), textStyle)
+        pStyle.setTextStyle(textStyle)
+        return pStyle
+    }
+
+    private fun applyStyles(from: SpanStyle, to: SkTextStyle) {
+        if (from.color != Color.Unset) {
+            to.setColor(from.color.toArgb())
+        }
+        from.fontFamily?.let {
+            val fontFamilies = fontLoader.ensureRegistered(it)
+            to.setFontFamilies(fontFamilies.toTypedArray())
+        }
+        // TODO: support [TextUnit.Em]
+        if (from.fontSize != TextUnit.Inherit) {
+            to.setFontSize(from.fontSize.value)
+        }
+    }
+
+    private fun textStylesToSkStyle(styles: List<Pair<Int, SpanStyle>>): SkTextStyle? {
+        if (styles.isEmpty()) {
+            return null
+        }
+        val skStyle = SkTextStyle()
+        for (s in styles.sortedBy { (priority, _) -> priority }.map { (_, v) -> v }) {
+            applyStyles(s, skStyle)
+        }
+        return skStyle
+    }
+}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelection.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelection.kt
new file mode 100644
index 0000000..2902926
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelection.kt
@@ -0,0 +1,123 @@
+/*
+ * 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.desktop
+
+import androidx.ui.core.Modifier
+import androidx.ui.core.Layout
+import androidx.ui.core.gesture.DragObserver
+import androidx.compose.Composable
+import androidx.ui.core.onPositioned
+import androidx.ui.geometry.Offset
+import kotlin.math.max
+import androidx.compose.remember
+import androidx.compose.state
+import androidx.ui.core.selection.Selection
+import androidx.ui.core.selection.SelectionRegistrarAmbient
+import androidx.compose.Providers
+import androidx.ui.core.pointerinput.PointerInputModifier
+import androidx.ui.core.pointerinput.PointerInputFilter
+import androidx.ui.core.composed
+import androidx.ui.core.gesture.rawDragGestureFilter
+import androidx.ui.core.gesture.rawPressStartGestureFilter
+
+@Composable
+private fun Wrap(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
+    Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
+        val placeables = measurables.map { measurable ->
+            measurable.measure(constraints)
+        }
+
+        val width = placeables.fold(0) { maxWidth, placeable ->
+            max(maxWidth, (placeable.width))
+        }
+
+        val height = placeables.fold(0) { minWidth, placeable ->
+            max(minWidth, (placeable.height))
+        }
+
+        layout(width, height) {
+            placeables.forEach { placeable ->
+                placeable.placeAbsolute(0, 0)
+            }
+        }
+    }
+}
+
+@Composable
+internal fun DesktopSelectionContainer(children: @Composable () -> Unit) {
+    val selection = state<Selection?> { null }
+    DesktopSelectionContainer(
+        selection = selection.value,
+        onSelectionChange = { selection.value = it },
+        children = children
+    )
+}
+
+private class PointerInputModifierImpl(override val pointerInputFilter: PointerInputFilter) :
+    PointerInputModifier
+
+private fun Modifier.selectionFilter(observer: DragObserver): Modifier = composed {
+    val glue = remember { DragGlue(observer) }
+    rawDragGestureFilter(glue, glue::started)
+        .rawPressStartGestureFilter(glue::startDrag, true)
+}
+
+private class DragGlue(val observer: DragObserver) : DragObserver by observer {
+    var started = false
+
+    fun startDrag(downPosition: Offset) {
+        started = true
+        observer.onStart(downPosition)
+    }
+
+    override fun onStop(velocity: Offset) {
+        started = false
+        observer.onStop(velocity)
+    }
+
+    override fun onCancel() {
+        started = false
+        observer.onCancel()
+    }
+}
+
+@Composable
+fun DesktopSelectionContainer(
+    selection: Selection?,
+    onSelectionChange: (Selection?) -> Unit,
+    children: @Composable () -> Unit
+) {
+    val registrarImpl = remember { DesktopSelectionRegistrar() }
+    val manager = remember { DesktopSelectionManager(registrarImpl) }
+
+    manager.onSelectionChange = onSelectionChange
+    manager.selection = selection
+
+    val gestureModifiers =
+        Modifier.selectionFilter(manager.observer)
+
+    val modifier = remember {
+        gestureModifiers.onPositioned {
+            manager.containerLayoutCoordinates = it
+        }
+    }
+
+    Providers(SelectionRegistrarAmbient provides registrarImpl) {
+        Wrap(modifier) {
+            children()
+        }
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionManager.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionManager.kt
new file mode 100644
index 0000000..9682623
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionManager.kt
@@ -0,0 +1,102 @@
+/*
+ * 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.desktop
+
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.ui.core.LayoutCoordinates
+import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.gesture.DragObserver
+import androidx.ui.geometry.Offset
+import androidx.ui.core.selection.Selection
+import androidx.ui.core.selection.Selectable
+
+internal class DesktopSelectionManager(private val selectionRegistrar: DesktopSelectionRegistrar) {
+    private var dragBeginPosition = Offset.Zero
+
+    private var dragTotalDistance = Offset.Zero
+
+    var containerLayoutCoordinates: LayoutCoordinates? = null
+
+    var clipboardManager: ClipboardManager? = null
+    var onSelectionChange: (Selection?) -> Unit = {}
+    var selection: Selection? = null
+
+    val observer = Observer()
+
+    inner class Observer : DragObserver {
+        override fun onStart(downPosition: Offset) {
+            mergeSelections(
+                startPosition = Offset(-1f, -1f),
+                endPosition = Offset(-1f, -1f),
+                previousSelection = selection
+            )
+            if (selection != null) onSelectionChange(null)
+            dragBeginPosition = downPosition
+            dragTotalDistance = Offset.Zero
+        }
+
+        override fun onDrag(dragDistance: Offset): Offset {
+            dragTotalDistance += dragDistance
+            val newSelection = mergeSelections(
+                startPosition = dragBeginPosition,
+                endPosition = dragBeginPosition + dragTotalDistance,
+                previousSelection = selection
+            )
+
+            if (newSelection != selection) onSelectionChange(newSelection)
+            return dragDistance
+        }
+    }
+
+    internal fun mergeSelections(
+        startPosition: Offset,
+        endPosition: Offset,
+        longPress: Boolean = false,
+        previousSelection: Selection? = null,
+        isStartHandle: Boolean = true
+    ): Selection? {
+
+        val newSelection = selectionRegistrar.sort(requireContainerCoordinates())
+            .fold(null) { mergedSelection: Selection?,
+                          handler: Selectable ->
+                merge(
+                    mergedSelection,
+                    handler.getSelection(
+                        startPosition = startPosition,
+                        endPosition = endPosition,
+                        containerLayoutCoordinates = requireContainerCoordinates(),
+                        longPress = longPress,
+                        previousSelection = previousSelection,
+                        isStartHandle = isStartHandle
+                    )
+                )
+            }
+        return newSelection
+    }
+
+    internal fun requireContainerCoordinates(): LayoutCoordinates {
+        val coordinates = containerLayoutCoordinates
+        require(coordinates != null)
+        require(coordinates.isAttached)
+        return coordinates
+    }
+}
+
+private fun merge(lhs: Selection?, rhs: Selection?): Selection? {
+    return lhs?.merge(rhs) ?: rhs
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionRegistrar.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionRegistrar.kt
new file mode 100644
index 0000000..7c3e79e
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionRegistrar.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.desktop
+
+import androidx.ui.core.LayoutCoordinates
+import androidx.ui.geometry.Offset
+import androidx.ui.core.selection.SelectionRegistrar
+import androidx.ui.core.selection.Selectable
+
+// based on androidx.ui.core.selection.SelectionRegistrarImpl
+internal class DesktopSelectionRegistrar : SelectionRegistrar {
+    internal var sorted: Boolean = false
+
+    private val _selectables = mutableListOf<Selectable>()
+    internal val selectables: List<Selectable>
+        get() = _selectables
+
+    internal var onPositionChangeCallback: (() -> Unit)? = null
+
+    override fun subscribe(selectable: Selectable): Selectable {
+        _selectables.add(selectable)
+        sorted = false
+        return selectable
+    }
+
+    override fun unsubscribe(selectable: Selectable) {
+        _selectables.remove(selectable)
+    }
+
+    fun sort(containerLayoutCoordinates: LayoutCoordinates): List<Selectable> {
+        if (!sorted) {
+            _selectables.sortWith(Comparator { a: Selectable, b: Selectable ->
+                val layoutCoordinatesA = a.getLayoutCoordinates()
+                val layoutCoordinatesB = b.getLayoutCoordinates()
+
+                val positionA =
+                    if (layoutCoordinatesA != null) containerLayoutCoordinates.childToLocal(
+                        layoutCoordinatesA,
+                        Offset.Zero
+                    )
+                    else Offset.Zero
+                val positionB =
+                    if (layoutCoordinatesB != null) containerLayoutCoordinates.childToLocal(
+                        layoutCoordinatesB,
+                        Offset.Zero
+                    )
+                    else Offset.Zero
+
+                if (positionA.y == positionB.y) compareValues(positionA.x, positionB.x)
+                else compareValues(positionA.y, positionB.y)
+            })
+            sorted = true
+        }
+        return selectables
+    }
+
+    override fun onPositionChange() {
+        sorted = false
+        onPositionChangeCallback?.invoke()
+    }
+}
\ No newline at end of file
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 aa19e73..f772d1b 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
@@ -15,6 +15,8 @@
  */
 package androidx.ui.desktop
 
+import androidx.ui.text.platform.paragraphActualFactory
+import androidx.ui.text.platform.paragraphIntrinsicsActualFactory
 import com.jogamp.opengl.GL
 import com.jogamp.opengl.GLAutoDrawable
 import com.jogamp.opengl.GLCapabilities
@@ -22,19 +24,19 @@
 import com.jogamp.opengl.GLProfile
 import com.jogamp.opengl.awt.GLCanvas
 import com.jogamp.opengl.util.FPSAnimator
-import org.jetbrains.skija.BackendRenderTarget
-import org.jetbrains.skija.Canvas
-import org.jetbrains.skija.Context
-import org.jetbrains.skija.JNI
-import org.jetbrains.skija.Surface
-import org.jetbrains.skija.ColorSpace
-import java.nio.IntBuffer
 import java.awt.event.KeyAdapter
 import java.awt.event.KeyEvent
 import java.awt.event.MouseAdapter
 import java.awt.event.MouseEvent
 import java.awt.event.MouseMotionAdapter
+import java.nio.IntBuffer
 import javax.swing.JFrame
+import org.jetbrains.skija.BackendRenderTarget
+import org.jetbrains.skija.Canvas
+import org.jetbrains.skija.ColorSpace
+import org.jetbrains.skija.Context
+import org.jetbrains.skija.JNI
+import org.jetbrains.skija.Surface
 
 private class SkijaState {
     var context: Context? = null
@@ -75,12 +77,18 @@
     height: Int,
     fps: Int = 0
 ) : JFrame() {
+    @OptIn(androidx.ui.text.platform.InternalPlatformTextApi::class)
     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")
+
+            @Suppress("DEPRECATION_ERROR")
+            paragraphIntrinsicsActualFactory = ::DesktopParagraphIntrinsics
+            @Suppress("DEPRECATION_ERROR")
+            paragraphActualFactory = ::DesktopParagraph
         }
     }
 
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 1787195..5e73423 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 androidx.lifecycle.ViewTreeViewModelStoreOwner
 import androidx.ui.core.setContent
 import androidx.ui.core.TextInputServiceAmbient
+import androidx.ui.core.FontLoaderAmbient
 import androidx.ui.input.TextInputService
 
 import javax.swing.SwingUtilities
@@ -63,13 +64,17 @@
             throw IllegalStateException("ViewModels creation is not supported")
         })
         viewGroup.setContent(Recomposer.current(), @Composable {
-            Providers(TextInputServiceAmbient provides TextInputService(
-                platformInputService), children = content)
+            Providers(
+                TextInputServiceAmbient provides TextInputService(
+                    platformInputService),
+                FontLoaderAmbient provides FontLoader()
+            ) {
+                DesktopSelectionContainer(children = content)
+            }
         })
-        val view = viewGroup.getChildAt(0)
-        view.onAttachedToWindow()
+        viewGroup.onAttachedToWindow()
 
-        this.renderer = Renderer(view, clocks, fps, platformInputService)
+        this.renderer = Renderer(viewGroup.getChildAt(0), clocks, fps, platformInputService)
         this.setFps(fps)
     }
 }
diff --git a/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/Runner.kt b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/Runner.kt
new file mode 100644
index 0000000..02f8d34
--- /dev/null
+++ b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/Runner.kt
@@ -0,0 +1,27 @@
+/*
+ * 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
+
+import org.junit.runner.JUnitCore
+import org.junit.internal.TextListener
+
+fun main() {
+    val junit = JUnitCore()
+    junit.addListener(TextListener(System.out))
+    junit.run(WrapperTest::class.java)
+    System.exit(0)
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/WrapperTest.kt b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/WrapperTest.kt
new file mode 100644
index 0000000..a89a873
--- /dev/null
+++ b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/WrapperTest.kt
@@ -0,0 +1,42 @@
+/*
+ * 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
+
+import androidx.ui.foundation.Text
+
+import java.awt.event.WindowEvent
+import javax.swing.WindowConstants
+
+import org.junit.Test
+
+class WrapperTest {
+    @Test
+    fun wrapWindow() {
+        val frame = SkiaWindow(width = 640, height = 480)
+
+        frame.title = "Test"
+        frame.setLocation(400, 400)
+        frame.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
+
+        frame.setContent {
+            Text("Simple")
+        }
+        frame.setVisible(true)
+
+        frame.dispatchEvent(WindowEvent(frame, WindowEvent.WINDOW_CLOSING))
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-foundation/api/0.1.0-dev15.txt b/ui/ui-foundation/api/0.1.0-dev15.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/0.1.0-dev15.txt
+++ b/ui/ui-foundation/api/0.1.0-dev15.txt
@@ -25,7 +25,6 @@
   }
 
   public final class ClickableKt {
-    method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
   }
 
   public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
   }
 
   public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
   }
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
     property public final boolean isAnimating;
     property public final float maxPosition;
     property public final float value;
-    field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+    field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
   }
 
   public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
     property public final String Selected;
     property public final String TemplatePercent;
     property public final String Unchecked;
-    field public static final androidx.ui.foundation.Strings! INSTANCE;
+    field public static final androidx.ui.foundation.Strings INSTANCE;
   }
 
   public final class TemporaryKt {
@@ -177,7 +176,7 @@
     method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
     method @Deprecated public androidx.ui.text.TextRange getSelection();
     method @Deprecated public String getText();
-    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
   }
 
   @Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
   public final class AndroidFlingSpline {
     method public double deceleration(float velocity, float friction);
     method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
-    field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+    field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
   }
 
   public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
   }
 
   public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
   }
 
   public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
   }
 
   public final class DraggableKt {
@@ -327,16 +326,13 @@
 package androidx.ui.foundation.selection {
 
   public final class SelectableKt {
-    method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
   }
 
   public final class ToggleableKt {
-    method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
-    method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
   }
 
   public enum ToggleableState {
+    method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.foundation.selection.ToggleableState[] values();
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
-    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
   }
 
   public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/current.txt b/ui/ui-foundation/api/current.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/current.txt
+++ b/ui/ui-foundation/api/current.txt
@@ -25,7 +25,6 @@
   }
 
   public final class ClickableKt {
-    method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
   }
 
   public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
   }
 
   public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
   }
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
     property public final boolean isAnimating;
     property public final float maxPosition;
     property public final float value;
-    field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+    field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
   }
 
   public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
     property public final String Selected;
     property public final String TemplatePercent;
     property public final String Unchecked;
-    field public static final androidx.ui.foundation.Strings! INSTANCE;
+    field public static final androidx.ui.foundation.Strings INSTANCE;
   }
 
   public final class TemporaryKt {
@@ -177,7 +176,7 @@
     method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
     method @Deprecated public androidx.ui.text.TextRange getSelection();
     method @Deprecated public String getText();
-    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
   }
 
   @Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
   public final class AndroidFlingSpline {
     method public double deceleration(float velocity, float friction);
     method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
-    field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+    field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
   }
 
   public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
   }
 
   public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
   }
 
   public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
   }
 
   public final class DraggableKt {
@@ -327,16 +326,13 @@
 package androidx.ui.foundation.selection {
 
   public final class SelectableKt {
-    method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
   }
 
   public final class ToggleableKt {
-    method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
-    method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
   }
 
   public enum ToggleableState {
+    method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.foundation.selection.ToggleableState[] values();
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
-    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
   }
 
   public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
@@ -25,7 +25,6 @@
   }
 
   public final class ClickableKt {
-    method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
   }
 
   public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
   }
 
   public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
   }
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
     property public final boolean isAnimating;
     property public final float maxPosition;
     property public final float value;
-    field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+    field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
   }
 
   public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
     property public final String Selected;
     property public final String TemplatePercent;
     property public final String Unchecked;
-    field public static final androidx.ui.foundation.Strings! INSTANCE;
+    field public static final androidx.ui.foundation.Strings INSTANCE;
   }
 
   public final class TemporaryKt {
@@ -177,7 +176,7 @@
     method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
     method @Deprecated public androidx.ui.text.TextRange getSelection();
     method @Deprecated public String getText();
-    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
   }
 
   @Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
   public final class AndroidFlingSpline {
     method public double deceleration(float velocity, float friction);
     method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
-    field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+    field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
   }
 
   public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
   }
 
   public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
   }
 
   public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
   }
 
   public final class DraggableKt {
@@ -327,16 +326,13 @@
 package androidx.ui.foundation.selection {
 
   public final class SelectableKt {
-    method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
   }
 
   public final class ToggleableKt {
-    method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
-    method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
   }
 
   public enum ToggleableState {
+    method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.foundation.selection.ToggleableState[] values();
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
-    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
   }
 
   public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/public_plus_experimental_current.txt b/ui/ui-foundation/api/public_plus_experimental_current.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/public_plus_experimental_current.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_current.txt
@@ -25,7 +25,6 @@
   }
 
   public final class ClickableKt {
-    method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
   }
 
   public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
   }
 
   public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
   }
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
     property public final boolean isAnimating;
     property public final float maxPosition;
     property public final float value;
-    field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+    field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
   }
 
   public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
     property public final String Selected;
     property public final String TemplatePercent;
     property public final String Unchecked;
-    field public static final androidx.ui.foundation.Strings! INSTANCE;
+    field public static final androidx.ui.foundation.Strings INSTANCE;
   }
 
   public final class TemporaryKt {
@@ -177,7 +176,7 @@
     method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
     method @Deprecated public androidx.ui.text.TextRange getSelection();
     method @Deprecated public String getText();
-    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
   }
 
   @Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
   public final class AndroidFlingSpline {
     method public double deceleration(float velocity, float friction);
     method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
-    field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+    field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
   }
 
   public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
   }
 
   public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
   }
 
   public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
   }
 
   public final class DraggableKt {
@@ -327,16 +326,13 @@
 package androidx.ui.foundation.selection {
 
   public final class SelectableKt {
-    method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
   }
 
   public final class ToggleableKt {
-    method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
-    method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
   }
 
   public enum ToggleableState {
+    method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.foundation.selection.ToggleableState[] values();
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
-    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
   }
 
   public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/restricted_0.1.0-dev15.txt b/ui/ui-foundation/api/restricted_0.1.0-dev15.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-foundation/api/restricted_0.1.0-dev15.txt
@@ -25,7 +25,6 @@
   }
 
   public final class ClickableKt {
-    method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
   }
 
   public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
   }
 
   public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
   }
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
     property public final boolean isAnimating;
     property public final float maxPosition;
     property public final float value;
-    field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+    field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
   }
 
   public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
     property public final String Selected;
     property public final String TemplatePercent;
     property public final String Unchecked;
-    field public static final androidx.ui.foundation.Strings! INSTANCE;
+    field public static final androidx.ui.foundation.Strings INSTANCE;
   }
 
   public final class TemporaryKt {
@@ -177,7 +176,7 @@
     method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
     method @Deprecated public androidx.ui.text.TextRange getSelection();
     method @Deprecated public String getText();
-    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
   }
 
   @Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
   public final class AndroidFlingSpline {
     method public double deceleration(float velocity, float friction);
     method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
-    field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+    field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
   }
 
   public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
   }
 
   public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
   }
 
   public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
   }
 
   public final class DraggableKt {
@@ -327,16 +326,13 @@
 package androidx.ui.foundation.selection {
 
   public final class SelectableKt {
-    method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
   }
 
   public final class ToggleableKt {
-    method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
-    method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
   }
 
   public enum ToggleableState {
+    method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.foundation.selection.ToggleableState[] values();
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
-    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
   }
 
   public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/restricted_current.txt b/ui/ui-foundation/api/restricted_current.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/restricted_current.txt
+++ b/ui/ui-foundation/api/restricted_current.txt
@@ -25,7 +25,6 @@
   }
 
   public final class ClickableKt {
-    method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
   }
 
   public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
   }
 
   public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
-    field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+    field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
   }
 
   @androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
     property public final boolean isAnimating;
     property public final float maxPosition;
     property public final float value;
-    field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+    field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
   }
 
   public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
     property public final String Selected;
     property public final String TemplatePercent;
     property public final String Unchecked;
-    field public static final androidx.ui.foundation.Strings! INSTANCE;
+    field public static final androidx.ui.foundation.Strings INSTANCE;
   }
 
   public final class TemporaryKt {
@@ -177,7 +176,7 @@
     method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
     method @Deprecated public androidx.ui.text.TextRange getSelection();
     method @Deprecated public String getText();
-    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+    field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
   }
 
   @Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
   public final class AndroidFlingSpline {
     method public double deceleration(float velocity, float friction);
     method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
-    field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+    field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
   }
 
   public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
   }
 
   public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
   }
 
   public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
-    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+    field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
   }
 
   public final class DraggableKt {
@@ -327,16 +326,13 @@
 package androidx.ui.foundation.selection {
 
   public final class SelectableKt {
-    method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
   }
 
   public final class ToggleableKt {
-    method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
-    method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
     method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({ 
     return <init>()
 }), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
   }
 
   public enum ToggleableState {
+    method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.foundation.selection.ToggleableState[] values();
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
     enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
-    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
   }
 
   public final class FoundationSemanticsPropertiesKt {
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 5543260..e68b163 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
@@ -20,7 +20,6 @@
 import androidx.compose.onCommit
 import androidx.compose.remember
 import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
 import androidx.ui.core.PointerEventPass
 import androidx.ui.core.PointerInputChange
 import androidx.ui.core.anyPositionChangeConsumed
@@ -41,65 +40,6 @@
 import androidx.ui.util.fastAny
 
 /**
- * Combines [tapGestureFilter] and Semantics for the clickable
- * components like Button.
- *
- * @sample androidx.ui.foundation.samples.ClickableSample
- *
- * @param onClick will be called when user clicked on the button
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- * @param enabled Controls the enabled state. When `false`, this component will not be
- * clickable
- * @param onClickLabel semantic / accessibility label for the [onClick] action
- * @param interactionState [InteractionState] that will be updated when this Clickable is
- * pressed, using [Interaction.Pressed]. Only initial (first) press will be recorded and added to
- * [InteractionState]
- *
- * @deprecated Use [clickable] modifier instead
- */
-@Deprecated(
-    "Clickable has been deprecated, use clickable modifier instead",
-    ReplaceWith(
-        "Box(modifier.clickable(onClick = onClick, enabled = enabled), children = children)",
-        "androidx.foundation.clickable",
-        "androidx.foundation.Box"
-    )
-)
-@Composable
-fun Clickable(
-    onClick: () -> Unit,
-    modifier: Modifier = Modifier,
-    enabled: Boolean = true,
-    onClickLabel: String? = null,
-    interactionState: InteractionState? = null,
-    children: @Composable () -> Unit
-) {
-    @Suppress("DEPRECATION")
-    PassThroughLayout(
-        modifier.clickable(
-            enabled,
-            onClickLabel,
-            tempFunToAvoidCreatingLambdaInsideClickable(interactionState),
-            onClick = onClick
-        ),
-        children
-    )
-}
-
-// when there is a lambda inside Clickable it is created as a file $Clickable\$2.class which
-// conflicts with similar lambda from Modifier.clickable which stored in $clickable\$2.class
-// on the case-insensitive FS. proper workaround would be to use different @JvmName on these
-// functions but it is currently not supported for composables b/157075847
-@Composable
-private fun tempFunToAvoidCreatingLambdaInsideClickable(
-    interactionState: InteractionState?
-): InteractionState {
-    return interactionState ?: remember { InteractionState() }
-}
-
-/**
  * Configure component to receive clicks via input or accessibility "click" event.
  *
  * Add this modifier to the element to make it clickable within its bounds.
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
index ae2c322..265a3e9 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
@@ -55,6 +55,7 @@
 import androidx.ui.text.TextLayoutResult
 import androidx.ui.text.TextRange
 import androidx.ui.text.TextStyle
+import androidx.ui.text.constrain
 import androidx.ui.unit.dp
 import org.jetbrains.annotations.TestOnly
 
@@ -129,13 +130,10 @@
 ) {
     val fullModel = state { androidx.ui.input.TextFieldValue() }
     if (fullModel.value.text != value.text || fullModel.value.selection != value.selection) {
-        val newSelection = TextRange(
-            value.selection.start.coerceIn(0, value.text.length),
-            value.selection.end.coerceIn(0, value.text.length)
-        )
+        @OptIn(InternalTextApi::class)
         fullModel.value = androidx.ui.input.TextFieldValue(
             text = value.text,
-            selection = newSelection
+            selection = value.selection.constrain(0, value.text.length)
         )
     }
 
@@ -249,14 +247,11 @@
 ) {
     val fullModel = state { androidx.ui.input.TextFieldValue() }
     if (fullModel.value != value) {
-        val newSelection = TextRange(
-            value.selection.start.coerceIn(0, value.text.length),
-            value.selection.end.coerceIn(0, value.text.length)
-        )
+        @OptIn(InternalTextApi::class)
         fullModel.value = androidx.ui.input.TextFieldValue(
             text = value.text,
-            selection = newSelection,
-            composition = value.composition
+            selection = value.selection.constrain(0, value.text.length),
+            composition = value.composition?.constrain(0, value.text.length)
         )
     }
 
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt
index 149e58b..d077b8c 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt
@@ -20,15 +20,18 @@
 import androidx.compose.ExperimentalComposeApi
 import androidx.compose.compositionReference
 import androidx.compose.currentComposer
+import androidx.compose.emit
 import androidx.compose.onDispose
 import androidx.compose.remember
-import androidx.ui.core.ContextAmbient
+import androidx.ui.core.LayoutNode
 import androidx.ui.core.Modifier
+import androidx.ui.core.Ref
 import androidx.ui.core.clipToBounds
 import androidx.ui.core.materialize
 import androidx.ui.foundation.gestures.DragDirection
 import androidx.ui.foundation.gestures.scrollable
 import androidx.ui.layout.Spacer
+import androidx.ui.node.UiApplier
 
 /**
  * A vertically scrolling list that only composes and lays out the currently visible items.
@@ -80,28 +83,42 @@
     state.recomposer = currentComposer.recomposer
     state.itemContent = itemContent
     state.items = items
-    state.context = ContextAmbient.current
     state.compositionRef = compositionReference()
     state.forceRecompose = true
 
     val dragDirection = if (isVertical) DragDirection.Vertical else DragDirection.Horizontal
-    androidx.ui.core.LayoutNode(
-        modifier = currentComposer.materialize(
-            modifier
-                .scrollable(
-                    dragDirection = dragDirection,
-                    scrollableState = androidx.ui.foundation.gestures.ScrollableState(
-                        onScrollDeltaConsumptionRequested =
-                        state.onScrollDeltaConsumptionRequestedListener
-                    )
+    val materialized = currentComposer.materialize(
+        modifier
+            .scrollable(
+                dragDirection = dragDirection,
+                scrollableState = androidx.ui.foundation.gestures.ScrollableState(
+                    onScrollDeltaConsumptionRequested =
+                    state.onScrollDeltaConsumptionRequestedListener
                 )
-                .clipToBounds()
-        ),
-        ref = state.rootNodeRef,
-        measureBlocks = state.measureBlocks
+            )
+            .clipToBounds()
+    )
+    emit<LayoutNode, UiApplier>(
+        ctor = LayoutEmitHelper.constructor,
+        update = {
+            set(materialized, LayoutEmitHelper.setModifier)
+            set(state.rootNodeRef, LayoutEmitHelper.setRef)
+            set(state.measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+        }
     )
     state.recomposeIfAttached()
     onDispose {
         state.disposeAllChildren()
     }
 }
+
+/**
+ * Object of pre-allocated lambdas used to make emits to LayoutNodes allocation-less.
+ */
+private object LayoutEmitHelper {
+    val constructor: () -> LayoutNode = { LayoutNode() }
+    val setModifier: LayoutNode.(Modifier) -> Unit = { this.modifier = it }
+    val setMeasureBlocks: LayoutNode.(LayoutNode.MeasureBlocks) -> Unit =
+        { this.measureBlocks = it }
+    val setRef: LayoutNode.(Ref<LayoutNode>) -> Unit = { this.ref = it }
+}
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt
index ad9399b..50d0d0e 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt
@@ -16,14 +16,13 @@
 
 package androidx.ui.foundation.lazy
 
-import android.content.Context
 import androidx.compose.Composable
+import androidx.compose.ComposableContract
 import androidx.compose.Composition
 import androidx.compose.CompositionReference
 import androidx.compose.ExperimentalComposeApi
 import androidx.compose.FrameManager
 import androidx.compose.Recomposer
-import androidx.compose.Untracked
 import androidx.ui.core.Constraints
 import androidx.ui.core.LayoutDirection
 import androidx.ui.core.LayoutNode
@@ -58,10 +57,6 @@
     var forceRecompose = false
     var compositionRef: CompositionReference? = null
     /**
-     * Should always be non-null when attached
-     */
-    var context: Context? = null
-    /**
      * Used to get the reference to populate [rootNode]
      */
     val rootNodeRef = Ref<LayoutNode>()
@@ -473,9 +468,13 @@
         } else {
             node = rootNode.children[layoutIndex.value]
         }
-        // TODO(b/150390669): Review use of @Untracked
+        // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
         @OptIn(ExperimentalComposeApi::class)
-        val composition = subcomposeInto(context!!, node, recomposer, compositionRef) @Untracked {
+        val composition = subcomposeInto(
+            node,
+            recomposer,
+            compositionRef
+        ) @ComposableContract(tracked = false) {
             itemContent(items[dataIndex.value])
         }
         compositionsForLayoutNodes[node] = composition
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
index 74acf8d..cac46d7 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
@@ -19,11 +19,8 @@
 import androidx.compose.Composable
 import androidx.compose.remember
 import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
 import androidx.ui.core.composed
-import androidx.ui.core.gesture.tapGestureFilter
 import androidx.ui.core.semantics.semantics
-import androidx.ui.foundation.Box
 import androidx.ui.foundation.Indication
 import androidx.ui.foundation.IndicationAmbient
 import androidx.ui.foundation.Interaction
@@ -36,55 +33,6 @@
 import androidx.ui.semantics.onClick
 
 /**
- * Component for representing one option out of many
- * in mutually exclusion set, e.g [androidx.ui.material.RadioGroup]
- *
- * Provides click handling as well as [Modifier.semantics] for accessibility
- *
- * @param selected whether or not this item is selected in mutually exclusion set
- * @param onClick callback to invoke when this item is clicked
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- *
- * @Deprecated Use [Modifier.selectable] instead.
- */
-@Deprecated(
-    "MutuallyExclusiveSetItem has been deprecated, use Modifier.selectable " +
-            "instead",
-    ReplaceWith(
-        "Box(modifier.selectable(" +
-                "selected = selected, " +
-                "onClick = onClick" +
-                ")," +
-                " children = children)",
-        "androidx.foundation.selectable",
-        "androidx.foundation.Box"
-    )
-)
-@Composable
-fun MutuallyExclusiveSetItem(
-    selected: Boolean,
-    onClick: () -> Unit,
-    modifier: Modifier = Modifier,
-    children: @Composable () -> Unit
-) {
-    // TODO: when semantics can be merged, we should make this use Clickable internally rather
-    //  than duplicating logic
-    Box(Modifier.semantics {
-        inMutuallyExclusiveGroup = true
-        this.selected = selected
-        this.accessibilityValue = if (selected) Strings.Selected else Strings.NotSelected
-        onClick(action = { onClick(); return@onClick true })
-    }) {
-        // TODO(b/150706555): This layout is temporary and should be removed once Semantics
-        //  is implemented with modifiers.
-        @Suppress("DEPRECATION")
-        PassThroughLayout(modifier.tapGestureFilter { onClick() }, children)
-    }
-}
-
-/**
  * Configure component to be selectable, usually as a part of a mutually exclusive group, where
  * only one item can be selected at any point in time. A typical example of mutually exclusive set
  * is [androidx.ui.material.RadioGroup]
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
index da91357..00fe81f 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
@@ -20,7 +20,6 @@
 import androidx.compose.onCommit
 import androidx.compose.remember
 import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
 import androidx.ui.core.composed
 import androidx.ui.core.gesture.pressIndicatorGestureFilter
 import androidx.ui.core.gesture.tapGestureFilter
@@ -40,49 +39,6 @@
 import androidx.ui.semantics.onClick
 
 /**
- * Combines [tapGestureFilter] and [Modifier.semantics] for the components that need to be
- * toggleable, like Switch.
- *
- * @see [TriStateToggleable] if you require support for an indeterminate state.
- *
- * @param value whether Toggleable is on or off
- * @param onValueChange callback to be invoked when toggleable is clicked,
- * therefore the change of the state in requested.
- * @param enabled whether or not this [Toggleable] will handle input events and appear
- * enabled for semantics purposes
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- * @Deprecated Use [Modifier.toggleable] instead.
- */
-@Deprecated(
-    "This component has been deprecated. Use [Modifier.toggleable] instead.",
-    ReplaceWith(
-        "Box(modifier.toggleable(" +
-                "value = value," +
-                " onValueChange = onValueChange," +
-                " enabled = enabled" +
-                "), children = children)",
-        "androidx.foundation.toggleable",
-        "androidx.foundation.Box"
-    )
-)
-@Composable
-fun Toggleable(
-    value: Boolean,
-    onValueChange: (Boolean) -> Unit,
-    enabled: Boolean = true,
-    modifier: Modifier = Modifier,
-    children: @Composable () -> Unit
-) {
-    @Suppress("DEPRECATION")
-    PassThroughLayout(
-        modifier.toggleable(value = value, onValueChange = onValueChange, enabled = enabled),
-        children
-    )
-}
-
-/**
  * Configure component to make it toggleable via input and accessibility events
  *
  * @sample androidx.ui.foundation.samples.ToggleableSample
@@ -115,54 +71,6 @@
 )
 
 /**
- * Combines [tapGestureFilter] and [Modifier.semantics] for the components with three states
- * like TriStateCheckbox.
- *
- * It supports three states: On, Off and Indeterminate.
- *
- * TriStateToggleable should be used when there are
- * dependent Toggleables associated to this component and those can have different values.
- *
- * @see [Toggleable] if you want to support only two states: on and off
- *
- * @param state current value for the component
- * @param onClick will be called when user toggles the toggleable.
- * @param enabled whether or not this [TriStateToggleable] will handle input events and
- * appear enabled for semantics purposes
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- *
- * @Deprecated Use [Modifier.triStateToggleable] instead.
- */
-@Deprecated(
-    "This component has been deprecated. Use [Modifier.triStateToggleable] instead.",
-    ReplaceWith(
-        "Box(modifier.triStateToggleable(" +
-                "state = state," +
-                " onClick = onClick," +
-                " enabled = enabled" +
-                "), children = children)",
-        "androidx.foundation.triStateToggleable",
-        "androidx.foundation.Box"
-    )
-)
-@Composable
-fun TriStateToggleable(
-    state: ToggleableState = On,
-    onClick: () -> Unit,
-    enabled: Boolean = true,
-    modifier: Modifier = Modifier,
-    children: @Composable () -> Unit
-) {
-    @Suppress("DEPRECATION")
-    PassThroughLayout(
-        modifier.triStateToggleable(state = state, onClick = onClick, enabled = enabled),
-        children
-    )
-}
-
-/**
  * Configure component to make it toggleable via input and accessibility events with three
  * states: On, Off and Indeterminate.
  *
diff --git a/ui/ui-geometry/api/0.1.0-dev15.txt b/ui/ui-geometry/api/0.1.0-dev15.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/0.1.0-dev15.txt
+++ b/ui/ui-geometry/api/0.1.0-dev15.txt
@@ -17,7 +17,7 @@
     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;
+    field public static final androidx.ui.geometry.Offset.Companion Companion;
   }
 
   public static final class Offset.Companion {
@@ -78,7 +78,7 @@
     method public static androidx.ui.geometry.RRect getZero();
     property public final float height;
     property public final float width;
-    field public static final androidx.ui.geometry.RRect.Companion! Companion;
+    field public static final androidx.ui.geometry.RRect.Companion Companion;
   }
 
   public static final class RRect.Companion {
@@ -135,7 +135,7 @@
     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;
+    field public static final androidx.ui.geometry.Radius.Companion Companion;
   }
 
   public static final class Radius.Companion {
@@ -189,7 +189,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Rect.Companion! Companion;
+    field public static final androidx.ui.geometry.Rect.Companion Companion;
   }
 
   public static final class Rect.Companion {
@@ -239,7 +239,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Size.Companion! Companion;
+    field public static final androidx.ui.geometry.Size.Companion Companion;
   }
 
   public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/api_lint.ignore b/ui/ui-geometry/api/api_lint.ignore
index c3e3a08..db1ca8b 100644
--- a/ui/ui-geometry/api/api_lint.ignore
+++ b/ui/ui-geometry/api/api_lint.ignore
@@ -3,3 +3,11 @@
     Acronyms should not be capitalized in method names: was `fromLTRB`, should this be `fromLtrb`?
 AcronymName: androidx.ui.geometry.Rect.Companion#fromLTWH(float, float, float, float):
     Acronyms should not be capitalized in method names: was `fromLTWH`, should this be `fromLtwh`?
+
+
+KotlinOperator: androidx.ui.geometry.RRect#contains(androidx.ui.geometry.Offset):
+    Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.ui.geometry.Rect#contains(androidx.ui.geometry.Offset):
+    Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.ui.geometry.Size#contains(androidx.ui.geometry.Offset):
+    Note that adding the `operator` keyword would allow calling this method using operator syntax
diff --git a/ui/ui-geometry/api/current.txt b/ui/ui-geometry/api/current.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/current.txt
+++ b/ui/ui-geometry/api/current.txt
@@ -17,7 +17,7 @@
     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;
+    field public static final androidx.ui.geometry.Offset.Companion Companion;
   }
 
   public static final class Offset.Companion {
@@ -78,7 +78,7 @@
     method public static androidx.ui.geometry.RRect getZero();
     property public final float height;
     property public final float width;
-    field public static final androidx.ui.geometry.RRect.Companion! Companion;
+    field public static final androidx.ui.geometry.RRect.Companion Companion;
   }
 
   public static final class RRect.Companion {
@@ -135,7 +135,7 @@
     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;
+    field public static final androidx.ui.geometry.Radius.Companion Companion;
   }
 
   public static final class Radius.Companion {
@@ -189,7 +189,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Rect.Companion! Companion;
+    field public static final androidx.ui.geometry.Rect.Companion Companion;
   }
 
   public static final class Rect.Companion {
@@ -239,7 +239,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Size.Companion! Companion;
+    field public static final androidx.ui.geometry.Size.Companion Companion;
   }
 
   public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
     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;
+    field public static final androidx.ui.geometry.Offset.Companion Companion;
   }
 
   public static final class Offset.Companion {
@@ -78,7 +78,7 @@
     method public static androidx.ui.geometry.RRect getZero();
     property public final float height;
     property public final float width;
-    field public static final androidx.ui.geometry.RRect.Companion! Companion;
+    field public static final androidx.ui.geometry.RRect.Companion Companion;
   }
 
   public static final class RRect.Companion {
@@ -135,7 +135,7 @@
     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;
+    field public static final androidx.ui.geometry.Radius.Companion Companion;
   }
 
   public static final class Radius.Companion {
@@ -189,7 +189,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Rect.Companion! Companion;
+    field public static final androidx.ui.geometry.Rect.Companion Companion;
   }
 
   public static final class Rect.Companion {
@@ -239,7 +239,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Size.Companion! Companion;
+    field public static final androidx.ui.geometry.Size.Companion Companion;
   }
 
   public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/public_plus_experimental_current.txt b/ui/ui-geometry/api/public_plus_experimental_current.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/public_plus_experimental_current.txt
+++ b/ui/ui-geometry/api/public_plus_experimental_current.txt
@@ -17,7 +17,7 @@
     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;
+    field public static final androidx.ui.geometry.Offset.Companion Companion;
   }
 
   public static final class Offset.Companion {
@@ -78,7 +78,7 @@
     method public static androidx.ui.geometry.RRect getZero();
     property public final float height;
     property public final float width;
-    field public static final androidx.ui.geometry.RRect.Companion! Companion;
+    field public static final androidx.ui.geometry.RRect.Companion Companion;
   }
 
   public static final class RRect.Companion {
@@ -135,7 +135,7 @@
     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;
+    field public static final androidx.ui.geometry.Radius.Companion Companion;
   }
 
   public static final class Radius.Companion {
@@ -189,7 +189,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Rect.Companion! Companion;
+    field public static final androidx.ui.geometry.Rect.Companion Companion;
   }
 
   public static final class Rect.Companion {
@@ -239,7 +239,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Size.Companion! Companion;
+    field public static final androidx.ui.geometry.Size.Companion Companion;
   }
 
   public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/restricted_0.1.0-dev15.txt b/ui/ui-geometry/api/restricted_0.1.0-dev15.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-geometry/api/restricted_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
     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;
+    field public static final androidx.ui.geometry.Offset.Companion Companion;
   }
 
   public static final class Offset.Companion {
@@ -78,7 +78,7 @@
     method public static androidx.ui.geometry.RRect getZero();
     property public final float height;
     property public final float width;
-    field public static final androidx.ui.geometry.RRect.Companion! Companion;
+    field public static final androidx.ui.geometry.RRect.Companion Companion;
   }
 
   public static final class RRect.Companion {
@@ -135,7 +135,7 @@
     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;
+    field public static final androidx.ui.geometry.Radius.Companion Companion;
   }
 
   public static final class Radius.Companion {
@@ -189,7 +189,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Rect.Companion! Companion;
+    field public static final androidx.ui.geometry.Rect.Companion Companion;
   }
 
   public static final class Rect.Companion {
@@ -239,7 +239,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Size.Companion! Companion;
+    field public static final androidx.ui.geometry.Size.Companion Companion;
   }
 
   public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/restricted_current.txt b/ui/ui-geometry/api/restricted_current.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/restricted_current.txt
+++ b/ui/ui-geometry/api/restricted_current.txt
@@ -17,7 +17,7 @@
     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;
+    field public static final androidx.ui.geometry.Offset.Companion Companion;
   }
 
   public static final class Offset.Companion {
@@ -78,7 +78,7 @@
     method public static androidx.ui.geometry.RRect getZero();
     property public final float height;
     property public final float width;
-    field public static final androidx.ui.geometry.RRect.Companion! Companion;
+    field public static final androidx.ui.geometry.RRect.Companion Companion;
   }
 
   public static final class RRect.Companion {
@@ -135,7 +135,7 @@
     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;
+    field public static final androidx.ui.geometry.Radius.Companion Companion;
   }
 
   public static final class Radius.Companion {
@@ -189,7 +189,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Rect.Companion! Companion;
+    field public static final androidx.ui.geometry.Rect.Companion Companion;
   }
 
   public static final class Rect.Companion {
@@ -239,7 +239,7 @@
     property public final float maxDimension;
     property public final float minDimension;
     property public final float width;
-    field public static final androidx.ui.geometry.Size.Companion! Companion;
+    field public static final androidx.ui.geometry.Size.Companion Companion;
   }
 
   public static final class Size.Companion {
diff --git a/ui/ui-graphics/api/0.1.0-dev15.txt b/ui/ui-graphics/api/0.1.0-dev15.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/0.1.0-dev15.txt
+++ b/ui/ui-graphics/api/0.1.0-dev15.txt
@@ -44,14 +44,14 @@
     method public android.graphics.Path getInternalPath();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
     method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
   }
 
   public enum BlendMode {
+    method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.BlendMode[] values();
     enum_constant public static final androidx.ui.graphics.BlendMode clear;
     enum_constant public static final androidx.ui.graphics.BlendMode color;
     enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
   }
 
   public enum ClipOp {
+    method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ClipOp[] values();
     enum_constant public static final androidx.ui.graphics.ClipOp difference;
     enum_constant public static final androidx.ui.graphics.ClipOp intersect;
   }
@@ -198,7 +202,7 @@
     method public long getValue();
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method public static String toString-impl(long $this);
-    field public static final androidx.ui.graphics.Color.Companion! Companion;
+    field public static final androidx.ui.graphics.Color.Companion Companion;
   }
 
   public static final class Color.Companion {
@@ -236,7 +240,7 @@
     method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
     method public androidx.ui.graphics.BlendMode getBlendMode();
     method public long getColor();
-    field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+    field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
   }
 
   public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
   }
 
   public enum FilterQuality {
+    method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.FilterQuality[] values();
     enum_constant public static final androidx.ui.graphics.FilterQuality high;
     enum_constant public static final androidx.ui.graphics.FilterQuality low;
     enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
   }
 
   public enum ImageAssetConfig {
+    method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ImageAssetConfig[] values();
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
   }
 
   public enum PaintingStyle {
+    method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PaintingStyle[] values();
     enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
     enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
   }
@@ -395,21 +405,21 @@
     method public androidx.ui.graphics.PathFillType getFillType();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
     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;
-    field public static final androidx.ui.graphics.Path.Companion! Companion;
+    field public static final androidx.ui.graphics.Path.Companion Companion;
   }
 
   public static final class Path.Companion {
@@ -417,11 +427,15 @@
   }
 
   public enum PathFillType {
+    method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathFillType[] values();
     enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
     enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
   }
 
   public enum PathOperation {
+    method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathOperation[] values();
     enum_constant public static final androidx.ui.graphics.PathOperation difference;
     enum_constant public static final androidx.ui.graphics.PathOperation intersect;
     enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
   }
 
   public enum PointMode {
+    method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PointMode[] values();
     enum_constant public static final androidx.ui.graphics.PointMode lines;
     enum_constant public static final androidx.ui.graphics.PointMode points;
     enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
     method public float getBlurRadius();
     method public long getColor();
     method public androidx.ui.geometry.Offset getOffset();
-    field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+    field public static final androidx.ui.graphics.Shadow.Companion Companion;
   }
 
   public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
   }
 
   public enum StrokeCap {
+    method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeCap[] values();
     enum_constant public static final androidx.ui.graphics.StrokeCap butt;
     enum_constant public static final androidx.ui.graphics.StrokeCap round;
     enum_constant public static final androidx.ui.graphics.StrokeCap square;
   }
 
   public enum StrokeJoin {
+    method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeJoin[] values();
     enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
     enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
     enum_constant public static final androidx.ui.graphics.StrokeJoin round;
   }
 
   public enum TileMode {
+    method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.TileMode[] values();
     enum_constant public static final androidx.ui.graphics.TileMode Clamp;
     enum_constant public static final androidx.ui.graphics.TileMode Mirror;
     enum_constant public static final androidx.ui.graphics.TileMode Repeated;
   }
 
   public enum VertexMode {
+    method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.VertexMode[] values();
     enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
     enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
     enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
 package androidx.ui.graphics.colorspace {
 
   public enum Adaptation {
+    method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.Adaptation[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
 
   public enum ColorModel {
     method public final int getComponentCount();
+    method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.ColorModel[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
     property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
     property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
     property public final androidx.ui.graphics.colorspace.Rgb Srgb;
-    field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
   }
 
   public class Connector {
@@ -648,10 +676,12 @@
     property public final androidx.ui.graphics.colorspace.WhitePoint D65;
     property public final androidx.ui.graphics.colorspace.WhitePoint D75;
     property public final androidx.ui.graphics.colorspace.WhitePoint E;
-    field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
   }
 
   public enum RenderIntent {
+    method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
     property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final androidx.ui.geometry.Size size;
-    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
   }
 
   public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
-    field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+    field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
   }
 
   public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
     method public float getMiter();
     method public android.graphics.PathEffect? getPathEffect();
     method public float getWidth();
-    field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
     field public static final float DefaultMiter = 4.0f;
     field public static final float HairlineWidth = 0.0f;
   }
@@ -865,25 +895,25 @@
   public final class PathBuilder {
     ctor public PathBuilder();
     method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder close();
     method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
     method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
     method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
-    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
     method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
-    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
   }
 
   public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
   }
 
   public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
-    field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+    field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
   }
 
   public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
   }
 
   public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeHorizontalTo(float x);
+    ctor public PathNode.RelativeHorizontalTo(float dx);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
-    method public float getX();
+    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+    method public float getDx();
   }
 
   public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeLineTo(float x, float y);
+    ctor public PathNode.RelativeLineTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeMoveTo(float x, float y);
+    ctor public PathNode.RelativeMoveTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+    ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeVerticalTo(float y);
+    ctor public PathNode.RelativeVerticalTo(float dy);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+    method public float getDy();
   }
 
   public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
     method public float[] toFloatArray();
     method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
     property public final inline java.util.List<java.lang.Float> m3storage;
-    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
   }
 
   public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
     property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
     property public final inline androidx.ui.graphics.vectormath.Vector3 up;
     property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
-    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
   }
 
   public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
   }
 
   public enum MatrixColumn {
+    method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
   }
 
   public enum VectorComponent {
+    method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/current.txt b/ui/ui-graphics/api/current.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/current.txt
+++ b/ui/ui-graphics/api/current.txt
@@ -44,14 +44,14 @@
     method public android.graphics.Path getInternalPath();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
     method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
   }
 
   public enum BlendMode {
+    method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.BlendMode[] values();
     enum_constant public static final androidx.ui.graphics.BlendMode clear;
     enum_constant public static final androidx.ui.graphics.BlendMode color;
     enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
   }
 
   public enum ClipOp {
+    method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ClipOp[] values();
     enum_constant public static final androidx.ui.graphics.ClipOp difference;
     enum_constant public static final androidx.ui.graphics.ClipOp intersect;
   }
@@ -198,7 +202,7 @@
     method public long getValue();
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method public static String toString-impl(long $this);
-    field public static final androidx.ui.graphics.Color.Companion! Companion;
+    field public static final androidx.ui.graphics.Color.Companion Companion;
   }
 
   public static final class Color.Companion {
@@ -236,7 +240,7 @@
     method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
     method public androidx.ui.graphics.BlendMode getBlendMode();
     method public long getColor();
-    field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+    field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
   }
 
   public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
   }
 
   public enum FilterQuality {
+    method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.FilterQuality[] values();
     enum_constant public static final androidx.ui.graphics.FilterQuality high;
     enum_constant public static final androidx.ui.graphics.FilterQuality low;
     enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
   }
 
   public enum ImageAssetConfig {
+    method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ImageAssetConfig[] values();
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
   }
 
   public enum PaintingStyle {
+    method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PaintingStyle[] values();
     enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
     enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
   }
@@ -395,21 +405,21 @@
     method public androidx.ui.graphics.PathFillType getFillType();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
     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;
-    field public static final androidx.ui.graphics.Path.Companion! Companion;
+    field public static final androidx.ui.graphics.Path.Companion Companion;
   }
 
   public static final class Path.Companion {
@@ -417,11 +427,15 @@
   }
 
   public enum PathFillType {
+    method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathFillType[] values();
     enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
     enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
   }
 
   public enum PathOperation {
+    method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathOperation[] values();
     enum_constant public static final androidx.ui.graphics.PathOperation difference;
     enum_constant public static final androidx.ui.graphics.PathOperation intersect;
     enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
   }
 
   public enum PointMode {
+    method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PointMode[] values();
     enum_constant public static final androidx.ui.graphics.PointMode lines;
     enum_constant public static final androidx.ui.graphics.PointMode points;
     enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
     method public float getBlurRadius();
     method public long getColor();
     method public androidx.ui.geometry.Offset getOffset();
-    field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+    field public static final androidx.ui.graphics.Shadow.Companion Companion;
   }
 
   public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
   }
 
   public enum StrokeCap {
+    method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeCap[] values();
     enum_constant public static final androidx.ui.graphics.StrokeCap butt;
     enum_constant public static final androidx.ui.graphics.StrokeCap round;
     enum_constant public static final androidx.ui.graphics.StrokeCap square;
   }
 
   public enum StrokeJoin {
+    method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeJoin[] values();
     enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
     enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
     enum_constant public static final androidx.ui.graphics.StrokeJoin round;
   }
 
   public enum TileMode {
+    method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.TileMode[] values();
     enum_constant public static final androidx.ui.graphics.TileMode Clamp;
     enum_constant public static final androidx.ui.graphics.TileMode Mirror;
     enum_constant public static final androidx.ui.graphics.TileMode Repeated;
   }
 
   public enum VertexMode {
+    method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.VertexMode[] values();
     enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
     enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
     enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
 package androidx.ui.graphics.colorspace {
 
   public enum Adaptation {
+    method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.Adaptation[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
 
   public enum ColorModel {
     method public final int getComponentCount();
+    method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.ColorModel[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
     property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
     property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
     property public final androidx.ui.graphics.colorspace.Rgb Srgb;
-    field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
   }
 
   public class Connector {
@@ -648,10 +676,12 @@
     property public final androidx.ui.graphics.colorspace.WhitePoint D65;
     property public final androidx.ui.graphics.colorspace.WhitePoint D75;
     property public final androidx.ui.graphics.colorspace.WhitePoint E;
-    field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
   }
 
   public enum RenderIntent {
+    method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
     property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final androidx.ui.geometry.Size size;
-    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
   }
 
   public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
-    field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+    field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
   }
 
   public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
     method public float getMiter();
     method public android.graphics.PathEffect? getPathEffect();
     method public float getWidth();
-    field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
     field public static final float DefaultMiter = 4.0f;
     field public static final float HairlineWidth = 0.0f;
   }
@@ -865,25 +895,25 @@
   public final class PathBuilder {
     ctor public PathBuilder();
     method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder close();
     method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
     method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
     method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
-    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
     method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
-    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
   }
 
   public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
   }
 
   public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
-    field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+    field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
   }
 
   public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
   }
 
   public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeHorizontalTo(float x);
+    ctor public PathNode.RelativeHorizontalTo(float dx);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
-    method public float getX();
+    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+    method public float getDx();
   }
 
   public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeLineTo(float x, float y);
+    ctor public PathNode.RelativeLineTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeMoveTo(float x, float y);
+    ctor public PathNode.RelativeMoveTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+    ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeVerticalTo(float y);
+    ctor public PathNode.RelativeVerticalTo(float dy);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+    method public float getDy();
   }
 
   public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
     method public float[] toFloatArray();
     method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
     property public final inline java.util.List<java.lang.Float> m3storage;
-    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
   }
 
   public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
     property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
     property public final inline androidx.ui.graphics.vectormath.Vector3 up;
     property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
-    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
   }
 
   public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
   }
 
   public enum MatrixColumn {
+    method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
   }
 
   public enum VectorComponent {
+    method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt
@@ -44,14 +44,14 @@
     method public android.graphics.Path getInternalPath();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
     method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
   }
 
   public enum BlendMode {
+    method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.BlendMode[] values();
     enum_constant public static final androidx.ui.graphics.BlendMode clear;
     enum_constant public static final androidx.ui.graphics.BlendMode color;
     enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
   }
 
   public enum ClipOp {
+    method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ClipOp[] values();
     enum_constant public static final androidx.ui.graphics.ClipOp difference;
     enum_constant public static final androidx.ui.graphics.ClipOp intersect;
   }
@@ -198,7 +202,7 @@
     method public long getValue();
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method public static String toString-impl(long $this);
-    field public static final androidx.ui.graphics.Color.Companion! Companion;
+    field public static final androidx.ui.graphics.Color.Companion Companion;
   }
 
   public static final class Color.Companion {
@@ -236,7 +240,7 @@
     method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
     method public androidx.ui.graphics.BlendMode getBlendMode();
     method public long getColor();
-    field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+    field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
   }
 
   public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
   }
 
   public enum FilterQuality {
+    method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.FilterQuality[] values();
     enum_constant public static final androidx.ui.graphics.FilterQuality high;
     enum_constant public static final androidx.ui.graphics.FilterQuality low;
     enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
   }
 
   public enum ImageAssetConfig {
+    method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ImageAssetConfig[] values();
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
   }
 
   public enum PaintingStyle {
+    method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PaintingStyle[] values();
     enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
     enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
   }
@@ -395,21 +405,21 @@
     method public androidx.ui.graphics.PathFillType getFillType();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
     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;
-    field public static final androidx.ui.graphics.Path.Companion! Companion;
+    field public static final androidx.ui.graphics.Path.Companion Companion;
   }
 
   public static final class Path.Companion {
@@ -417,11 +427,15 @@
   }
 
   public enum PathFillType {
+    method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathFillType[] values();
     enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
     enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
   }
 
   public enum PathOperation {
+    method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathOperation[] values();
     enum_constant public static final androidx.ui.graphics.PathOperation difference;
     enum_constant public static final androidx.ui.graphics.PathOperation intersect;
     enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
   }
 
   public enum PointMode {
+    method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PointMode[] values();
     enum_constant public static final androidx.ui.graphics.PointMode lines;
     enum_constant public static final androidx.ui.graphics.PointMode points;
     enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
     method public float getBlurRadius();
     method public long getColor();
     method public androidx.ui.geometry.Offset getOffset();
-    field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+    field public static final androidx.ui.graphics.Shadow.Companion Companion;
   }
 
   public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
   }
 
   public enum StrokeCap {
+    method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeCap[] values();
     enum_constant public static final androidx.ui.graphics.StrokeCap butt;
     enum_constant public static final androidx.ui.graphics.StrokeCap round;
     enum_constant public static final androidx.ui.graphics.StrokeCap square;
   }
 
   public enum StrokeJoin {
+    method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeJoin[] values();
     enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
     enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
     enum_constant public static final androidx.ui.graphics.StrokeJoin round;
   }
 
   public enum TileMode {
+    method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.TileMode[] values();
     enum_constant public static final androidx.ui.graphics.TileMode Clamp;
     enum_constant public static final androidx.ui.graphics.TileMode Mirror;
     enum_constant public static final androidx.ui.graphics.TileMode Repeated;
   }
 
   public enum VertexMode {
+    method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.VertexMode[] values();
     enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
     enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
     enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
 package androidx.ui.graphics.colorspace {
 
   public enum Adaptation {
+    method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.Adaptation[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
 
   public enum ColorModel {
     method public final int getComponentCount();
+    method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.ColorModel[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
     property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
     property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
     property public final androidx.ui.graphics.colorspace.Rgb Srgb;
-    field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
   }
 
   public class Connector {
@@ -648,10 +676,12 @@
     property public final androidx.ui.graphics.colorspace.WhitePoint D65;
     property public final androidx.ui.graphics.colorspace.WhitePoint D75;
     property public final androidx.ui.graphics.colorspace.WhitePoint E;
-    field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
   }
 
   public enum RenderIntent {
+    method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
     property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final androidx.ui.geometry.Size size;
-    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
   }
 
   public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
-    field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+    field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
   }
 
   public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
     method public float getMiter();
     method public android.graphics.PathEffect? getPathEffect();
     method public float getWidth();
-    field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
     field public static final float DefaultMiter = 4.0f;
     field public static final float HairlineWidth = 0.0f;
   }
@@ -865,25 +895,25 @@
   public final class PathBuilder {
     ctor public PathBuilder();
     method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder close();
     method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
     method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
     method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
-    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
     method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
-    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
   }
 
   public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
   }
 
   public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
-    field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+    field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
   }
 
   public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
   }
 
   public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeHorizontalTo(float x);
+    ctor public PathNode.RelativeHorizontalTo(float dx);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
-    method public float getX();
+    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+    method public float getDx();
   }
 
   public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeLineTo(float x, float y);
+    ctor public PathNode.RelativeLineTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeMoveTo(float x, float y);
+    ctor public PathNode.RelativeMoveTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+    ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeVerticalTo(float y);
+    ctor public PathNode.RelativeVerticalTo(float dy);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+    method public float getDy();
   }
 
   public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
     method public float[] toFloatArray();
     method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
     property public final inline java.util.List<java.lang.Float> m3storage;
-    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
   }
 
   public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
     property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
     property public final inline androidx.ui.graphics.vectormath.Vector3 up;
     property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
-    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
   }
 
   public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
   }
 
   public enum MatrixColumn {
+    method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
   }
 
   public enum VectorComponent {
+    method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/public_plus_experimental_current.txt b/ui/ui-graphics/api/public_plus_experimental_current.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/public_plus_experimental_current.txt
+++ b/ui/ui-graphics/api/public_plus_experimental_current.txt
@@ -44,14 +44,14 @@
     method public android.graphics.Path getInternalPath();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
     method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
   }
 
   public enum BlendMode {
+    method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.BlendMode[] values();
     enum_constant public static final androidx.ui.graphics.BlendMode clear;
     enum_constant public static final androidx.ui.graphics.BlendMode color;
     enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
   }
 
   public enum ClipOp {
+    method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ClipOp[] values();
     enum_constant public static final androidx.ui.graphics.ClipOp difference;
     enum_constant public static final androidx.ui.graphics.ClipOp intersect;
   }
@@ -198,7 +202,7 @@
     method public long getValue();
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method public static String toString-impl(long $this);
-    field public static final androidx.ui.graphics.Color.Companion! Companion;
+    field public static final androidx.ui.graphics.Color.Companion Companion;
   }
 
   public static final class Color.Companion {
@@ -236,7 +240,7 @@
     method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
     method public androidx.ui.graphics.BlendMode getBlendMode();
     method public long getColor();
-    field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+    field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
   }
 
   public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
   }
 
   public enum FilterQuality {
+    method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.FilterQuality[] values();
     enum_constant public static final androidx.ui.graphics.FilterQuality high;
     enum_constant public static final androidx.ui.graphics.FilterQuality low;
     enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
   }
 
   public enum ImageAssetConfig {
+    method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ImageAssetConfig[] values();
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
   }
 
   public enum PaintingStyle {
+    method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PaintingStyle[] values();
     enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
     enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
   }
@@ -395,21 +405,21 @@
     method public androidx.ui.graphics.PathFillType getFillType();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
     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;
-    field public static final androidx.ui.graphics.Path.Companion! Companion;
+    field public static final androidx.ui.graphics.Path.Companion Companion;
   }
 
   public static final class Path.Companion {
@@ -417,11 +427,15 @@
   }
 
   public enum PathFillType {
+    method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathFillType[] values();
     enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
     enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
   }
 
   public enum PathOperation {
+    method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathOperation[] values();
     enum_constant public static final androidx.ui.graphics.PathOperation difference;
     enum_constant public static final androidx.ui.graphics.PathOperation intersect;
     enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
   }
 
   public enum PointMode {
+    method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PointMode[] values();
     enum_constant public static final androidx.ui.graphics.PointMode lines;
     enum_constant public static final androidx.ui.graphics.PointMode points;
     enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
     method public float getBlurRadius();
     method public long getColor();
     method public androidx.ui.geometry.Offset getOffset();
-    field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+    field public static final androidx.ui.graphics.Shadow.Companion Companion;
   }
 
   public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
   }
 
   public enum StrokeCap {
+    method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeCap[] values();
     enum_constant public static final androidx.ui.graphics.StrokeCap butt;
     enum_constant public static final androidx.ui.graphics.StrokeCap round;
     enum_constant public static final androidx.ui.graphics.StrokeCap square;
   }
 
   public enum StrokeJoin {
+    method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeJoin[] values();
     enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
     enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
     enum_constant public static final androidx.ui.graphics.StrokeJoin round;
   }
 
   public enum TileMode {
+    method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.TileMode[] values();
     enum_constant public static final androidx.ui.graphics.TileMode Clamp;
     enum_constant public static final androidx.ui.graphics.TileMode Mirror;
     enum_constant public static final androidx.ui.graphics.TileMode Repeated;
   }
 
   public enum VertexMode {
+    method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.VertexMode[] values();
     enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
     enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
     enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
 package androidx.ui.graphics.colorspace {
 
   public enum Adaptation {
+    method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.Adaptation[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
 
   public enum ColorModel {
     method public final int getComponentCount();
+    method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.ColorModel[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
     property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
     property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
     property public final androidx.ui.graphics.colorspace.Rgb Srgb;
-    field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
   }
 
   public class Connector {
@@ -648,10 +676,12 @@
     property public final androidx.ui.graphics.colorspace.WhitePoint D65;
     property public final androidx.ui.graphics.colorspace.WhitePoint D75;
     property public final androidx.ui.graphics.colorspace.WhitePoint E;
-    field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
   }
 
   public enum RenderIntent {
+    method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
     property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final androidx.ui.geometry.Size size;
-    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
   }
 
   public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
-    field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+    field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
   }
 
   public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
     method public float getMiter();
     method public android.graphics.PathEffect? getPathEffect();
     method public float getWidth();
-    field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
     field public static final float DefaultMiter = 4.0f;
     field public static final float HairlineWidth = 0.0f;
   }
@@ -865,25 +895,25 @@
   public final class PathBuilder {
     ctor public PathBuilder();
     method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder close();
     method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
     method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
     method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
-    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
     method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
-    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
   }
 
   public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
   }
 
   public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
-    field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+    field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
   }
 
   public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
   }
 
   public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeHorizontalTo(float x);
+    ctor public PathNode.RelativeHorizontalTo(float dx);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
-    method public float getX();
+    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+    method public float getDx();
   }
 
   public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeLineTo(float x, float y);
+    ctor public PathNode.RelativeLineTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeMoveTo(float x, float y);
+    ctor public PathNode.RelativeMoveTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+    ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeVerticalTo(float y);
+    ctor public PathNode.RelativeVerticalTo(float dy);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+    method public float getDy();
   }
 
   public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
     method public float[] toFloatArray();
     method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
     property public final inline java.util.List<java.lang.Float> m3storage;
-    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
   }
 
   public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
     property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
     property public final inline androidx.ui.graphics.vectormath.Vector3 up;
     property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
-    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
   }
 
   public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
   }
 
   public enum MatrixColumn {
+    method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
   }
 
   public enum VectorComponent {
+    method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/restricted_0.1.0-dev15.txt b/ui/ui-graphics/api/restricted_0.1.0-dev15.txt
index 79ad302..5fc211b 100644
--- a/ui/ui-graphics/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-graphics/api/restricted_0.1.0-dev15.txt
@@ -76,14 +76,14 @@
     method public android.graphics.Path getInternalPath();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
     method public void shift(androidx.ui.geometry.Offset offset);
@@ -110,6 +110,8 @@
   }
 
   public enum BlendMode {
+    method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.BlendMode[] values();
     enum_constant public static final androidx.ui.graphics.BlendMode clear;
     enum_constant public static final androidx.ui.graphics.BlendMode color;
     enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -207,6 +209,8 @@
   }
 
   public enum ClipOp {
+    method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ClipOp[] values();
     enum_constant public static final androidx.ui.graphics.ClipOp difference;
     enum_constant public static final androidx.ui.graphics.ClipOp intersect;
   }
@@ -231,7 +235,7 @@
     method public long getValue();
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method public static String toString-impl(long $this);
-    field public static final androidx.ui.graphics.Color.Companion! Companion;
+    field public static final androidx.ui.graphics.Color.Companion Companion;
   }
 
   public static final class Color.Companion {
@@ -269,7 +273,7 @@
     method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
     method public androidx.ui.graphics.BlendMode getBlendMode();
     method public long getColor();
-    field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+    field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
   }
 
   public static final class ColorFilter.Companion {
@@ -291,6 +295,8 @@
   }
 
   public enum FilterQuality {
+    method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.FilterQuality[] values();
     enum_constant public static final androidx.ui.graphics.FilterQuality high;
     enum_constant public static final androidx.ui.graphics.FilterQuality low;
     enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -316,6 +322,8 @@
   }
 
   public enum ImageAssetConfig {
+    method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ImageAssetConfig[] values();
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -409,6 +417,8 @@
   }
 
   public enum PaintingStyle {
+    method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PaintingStyle[] values();
     enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
     enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
   }
@@ -428,21 +438,21 @@
     method public androidx.ui.graphics.PathFillType getFillType();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
     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;
-    field public static final androidx.ui.graphics.Path.Companion! Companion;
+    field public static final androidx.ui.graphics.Path.Companion Companion;
   }
 
   public static final class Path.Companion {
@@ -450,11 +460,15 @@
   }
 
   public enum PathFillType {
+    method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathFillType[] values();
     enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
     enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
   }
 
   public enum PathOperation {
+    method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathOperation[] values();
     enum_constant public static final androidx.ui.graphics.PathOperation difference;
     enum_constant public static final androidx.ui.graphics.PathOperation intersect;
     enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -473,6 +487,8 @@
   }
 
   public enum PointMode {
+    method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PointMode[] values();
     enum_constant public static final androidx.ui.graphics.PointMode lines;
     enum_constant public static final androidx.ui.graphics.PointMode points;
     enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -515,7 +531,7 @@
     method public float getBlurRadius();
     method public long getColor();
     method public androidx.ui.geometry.Offset getOffset();
-    field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+    field public static final androidx.ui.graphics.Shadow.Companion Companion;
   }
 
   public static final class Shadow.Companion {
@@ -539,24 +555,32 @@
   }
 
   public enum StrokeCap {
+    method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeCap[] values();
     enum_constant public static final androidx.ui.graphics.StrokeCap butt;
     enum_constant public static final androidx.ui.graphics.StrokeCap round;
     enum_constant public static final androidx.ui.graphics.StrokeCap square;
   }
 
   public enum StrokeJoin {
+    method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeJoin[] values();
     enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
     enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
     enum_constant public static final androidx.ui.graphics.StrokeJoin round;
   }
 
   public enum TileMode {
+    method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.TileMode[] values();
     enum_constant public static final androidx.ui.graphics.TileMode Clamp;
     enum_constant public static final androidx.ui.graphics.TileMode Mirror;
     enum_constant public static final androidx.ui.graphics.TileMode Repeated;
   }
 
   public enum VertexMode {
+    method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.VertexMode[] values();
     enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
     enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
     enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -580,6 +604,8 @@
 package androidx.ui.graphics.colorspace {
 
   public enum Adaptation {
+    method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.Adaptation[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -587,6 +613,8 @@
 
   public enum ColorModel {
     method public final int getComponentCount();
+    method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.ColorModel[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -651,7 +679,7 @@
     property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
     property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
     property public final androidx.ui.graphics.colorspace.Rgb Srgb;
-    field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
   }
 
   public class Connector {
@@ -681,10 +709,12 @@
     property public final androidx.ui.graphics.colorspace.WhitePoint D65;
     property public final androidx.ui.graphics.colorspace.WhitePoint D75;
     property public final androidx.ui.graphics.colorspace.WhitePoint E;
-    field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
   }
 
   public enum RenderIntent {
+    method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -784,7 +814,7 @@
     property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final androidx.ui.geometry.Size size;
-    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
     field @kotlin.PublishedApi internal androidx.ui.graphics.Canvas canvas;
     field @kotlin.PublishedApi internal final androidx.ui.graphics.drawscope.DrawTransform transform;
   }
@@ -833,7 +863,7 @@
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
-    field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+    field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
   }
 
   public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -850,7 +880,7 @@
     method public float getMiter();
     method public android.graphics.PathEffect? getPathEffect();
     method public float getWidth();
-    field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
     field public static final float DefaultMiter = 4.0f;
     field public static final float HairlineWidth = 0.0f;
   }
@@ -901,25 +931,25 @@
   public final class PathBuilder {
     ctor public PathBuilder();
     method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder close();
     method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
     method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
     method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
-    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
     method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
-    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
   }
 
   public abstract sealed class PathNode {
@@ -947,7 +977,7 @@
   }
 
   public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
-    field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+    field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
   }
 
   public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1064,70 +1094,70 @@
   }
 
   public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeHorizontalTo(float x);
+    ctor public PathNode.RelativeHorizontalTo(float dx);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
-    method public float getX();
+    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+    method public float getDx();
   }
 
   public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeLineTo(float x, float y);
+    ctor public PathNode.RelativeLineTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeMoveTo(float x, float y);
+    ctor public PathNode.RelativeMoveTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+    ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeVerticalTo(float y);
+    ctor public PathNode.RelativeVerticalTo(float dy);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+    method public float getDy();
   }
 
   public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1185,7 +1215,7 @@
     method public float[] toFloatArray();
     method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
     property public final inline java.util.List<java.lang.Float> m3storage;
-    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
   }
 
   public static final class Matrix3.Companion {
@@ -1265,7 +1295,7 @@
     property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
     property public final inline androidx.ui.graphics.vectormath.Vector3 up;
     property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
-    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
   }
 
   public static final class Matrix4.Companion {
@@ -1292,6 +1322,8 @@
   }
 
   public enum MatrixColumn {
+    method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1580,6 +1612,8 @@
   }
 
   public enum VectorComponent {
+    method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/restricted_current.txt b/ui/ui-graphics/api/restricted_current.txt
index 79ad302..5fc211b 100644
--- a/ui/ui-graphics/api/restricted_current.txt
+++ b/ui/ui-graphics/api/restricted_current.txt
@@ -76,14 +76,14 @@
     method public android.graphics.Path getInternalPath();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType value);
     method public void shift(androidx.ui.geometry.Offset offset);
@@ -110,6 +110,8 @@
   }
 
   public enum BlendMode {
+    method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.BlendMode[] values();
     enum_constant public static final androidx.ui.graphics.BlendMode clear;
     enum_constant public static final androidx.ui.graphics.BlendMode color;
     enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -207,6 +209,8 @@
   }
 
   public enum ClipOp {
+    method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ClipOp[] values();
     enum_constant public static final androidx.ui.graphics.ClipOp difference;
     enum_constant public static final androidx.ui.graphics.ClipOp intersect;
   }
@@ -231,7 +235,7 @@
     method public long getValue();
     method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
     method public static String toString-impl(long $this);
-    field public static final androidx.ui.graphics.Color.Companion! Companion;
+    field public static final androidx.ui.graphics.Color.Companion Companion;
   }
 
   public static final class Color.Companion {
@@ -269,7 +273,7 @@
     method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
     method public androidx.ui.graphics.BlendMode getBlendMode();
     method public long getColor();
-    field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+    field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
   }
 
   public static final class ColorFilter.Companion {
@@ -291,6 +295,8 @@
   }
 
   public enum FilterQuality {
+    method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.FilterQuality[] values();
     enum_constant public static final androidx.ui.graphics.FilterQuality high;
     enum_constant public static final androidx.ui.graphics.FilterQuality low;
     enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -316,6 +322,8 @@
   }
 
   public enum ImageAssetConfig {
+    method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.ImageAssetConfig[] values();
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
     enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -409,6 +417,8 @@
   }
 
   public enum PaintingStyle {
+    method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PaintingStyle[] values();
     enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
     enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
   }
@@ -428,21 +438,21 @@
     method public androidx.ui.graphics.PathFillType getFillType();
     method public boolean isConvex();
     method public boolean isEmpty();
-    method public void lineTo(float dx, float dy);
-    method public void moveTo(float dx, float dy);
+    method public void lineTo(float x, float y);
+    method public void moveTo(float x, float y);
     method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
     method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
-    method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+    method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public void relativeLineTo(float dx, float dy);
     method public void relativeMoveTo(float dx, float dy);
-    method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+    method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
     method public void reset();
     method public void setFillType(androidx.ui.graphics.PathFillType p);
     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;
-    field public static final androidx.ui.graphics.Path.Companion! Companion;
+    field public static final androidx.ui.graphics.Path.Companion Companion;
   }
 
   public static final class Path.Companion {
@@ -450,11 +460,15 @@
   }
 
   public enum PathFillType {
+    method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathFillType[] values();
     enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
     enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
   }
 
   public enum PathOperation {
+    method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PathOperation[] values();
     enum_constant public static final androidx.ui.graphics.PathOperation difference;
     enum_constant public static final androidx.ui.graphics.PathOperation intersect;
     enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -473,6 +487,8 @@
   }
 
   public enum PointMode {
+    method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.PointMode[] values();
     enum_constant public static final androidx.ui.graphics.PointMode lines;
     enum_constant public static final androidx.ui.graphics.PointMode points;
     enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -515,7 +531,7 @@
     method public float getBlurRadius();
     method public long getColor();
     method public androidx.ui.geometry.Offset getOffset();
-    field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+    field public static final androidx.ui.graphics.Shadow.Companion Companion;
   }
 
   public static final class Shadow.Companion {
@@ -539,24 +555,32 @@
   }
 
   public enum StrokeCap {
+    method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeCap[] values();
     enum_constant public static final androidx.ui.graphics.StrokeCap butt;
     enum_constant public static final androidx.ui.graphics.StrokeCap round;
     enum_constant public static final androidx.ui.graphics.StrokeCap square;
   }
 
   public enum StrokeJoin {
+    method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.StrokeJoin[] values();
     enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
     enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
     enum_constant public static final androidx.ui.graphics.StrokeJoin round;
   }
 
   public enum TileMode {
+    method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.TileMode[] values();
     enum_constant public static final androidx.ui.graphics.TileMode Clamp;
     enum_constant public static final androidx.ui.graphics.TileMode Mirror;
     enum_constant public static final androidx.ui.graphics.TileMode Repeated;
   }
 
   public enum VertexMode {
+    method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.VertexMode[] values();
     enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
     enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
     enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -580,6 +604,8 @@
 package androidx.ui.graphics.colorspace {
 
   public enum Adaptation {
+    method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.Adaptation[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
     enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -587,6 +613,8 @@
 
   public enum ColorModel {
     method public final int getComponentCount();
+    method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.ColorModel[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
     enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -651,7 +679,7 @@
     property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
     property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
     property public final androidx.ui.graphics.colorspace.Rgb Srgb;
-    field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
   }
 
   public class Connector {
@@ -681,10 +709,12 @@
     property public final androidx.ui.graphics.colorspace.WhitePoint D65;
     property public final androidx.ui.graphics.colorspace.WhitePoint D75;
     property public final androidx.ui.graphics.colorspace.WhitePoint E;
-    field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+    field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
   }
 
   public enum RenderIntent {
+    method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
     enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -784,7 +814,7 @@
     property public final androidx.ui.geometry.Offset center;
     property public abstract androidx.ui.core.LayoutDirection layoutDirection;
     property public final androidx.ui.geometry.Size size;
-    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
     field @kotlin.PublishedApi internal androidx.ui.graphics.Canvas canvas;
     field @kotlin.PublishedApi internal final androidx.ui.graphics.drawscope.DrawTransform transform;
   }
@@ -833,7 +863,7 @@
   }
 
   public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
-    field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+    field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
   }
 
   public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -850,7 +880,7 @@
     method public float getMiter();
     method public android.graphics.PathEffect? getPathEffect();
     method public float getWidth();
-    field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+    field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
     field public static final float DefaultMiter = 4.0f;
     field public static final float HairlineWidth = 0.0f;
   }
@@ -901,25 +931,25 @@
   public final class PathBuilder {
     ctor public PathBuilder();
     method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder close();
     method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
     method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
     method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
     method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
-    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+    method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
     method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
-    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+    method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
     method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
     method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
-    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+    method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
     method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
-    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+    method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
   }
 
   public abstract sealed class PathNode {
@@ -947,7 +977,7 @@
   }
 
   public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
-    field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+    field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
   }
 
   public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1064,70 +1094,70 @@
   }
 
   public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeHorizontalTo(float x);
+    ctor public PathNode.RelativeHorizontalTo(float dx);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
-    method public float getX();
+    method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+    method public float getDx();
   }
 
   public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeLineTo(float x, float y);
+    ctor public PathNode.RelativeLineTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeMoveTo(float x, float y);
+    ctor public PathNode.RelativeMoveTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+    ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
     method public float component1();
     method public float component2();
     method public float component3();
     method public float component4();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
-    method public float getX1();
-    method public float getX2();
-    method public float getY1();
-    method public float getY2();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+    method public float getDx1();
+    method public float getDx2();
+    method public float getDy1();
+    method public float getDy2();
   }
 
   public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+    ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
     method public float component1();
     method public float component2();
-    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
-    method public float getX();
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+    method public float getDx();
+    method public float getDy();
   }
 
   public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
-    ctor public PathNode.RelativeVerticalTo(float y);
+    ctor public PathNode.RelativeVerticalTo(float dy);
     method public float component1();
-    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
-    method public float getY();
+    method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+    method public float getDy();
   }
 
   public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1185,7 +1215,7 @@
     method public float[] toFloatArray();
     method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
     property public final inline java.util.List<java.lang.Float> m3storage;
-    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
   }
 
   public static final class Matrix3.Companion {
@@ -1265,7 +1295,7 @@
     property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
     property public final inline androidx.ui.graphics.vectormath.Vector3 up;
     property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
-    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+    field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
   }
 
   public static final class Matrix4.Companion {
@@ -1292,6 +1322,8 @@
   }
 
   public enum MatrixColumn {
+    method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
     enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1580,6 +1612,8 @@
   }
 
   public enum VectorComponent {
+    method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
     enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt
index 6f48e17..e199923 100644
--- a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt
+++ b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt
@@ -24,7 +24,9 @@
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.ImageAsset
 import androidx.ui.graphics.Paint
+import androidx.ui.graphics.PointMode
 import androidx.ui.graphics.SolidColor
+import androidx.ui.graphics.StrokeCap
 import androidx.ui.graphics.compositeOver
 import androidx.ui.graphics.toPixelMap
 import org.junit.Assert.assertEquals
@@ -593,6 +595,160 @@
         }
     }
 
+    @Test
+    fun testDrawLineStrokeParametersAreApplied() {
+        val width = 200
+        val height = 200
+        val start = Offset.Zero
+        val end = Offset(width.toFloat(), height.toFloat())
+        val strokeWidth = 10.0f
+        // Test that colors are rendered with the correct stroke parameters
+        testDrawScopeAndCanvasAreEquivalent(
+            width,
+            height,
+            {
+                drawLine(
+                    Color.Cyan,
+                    start,
+                    end,
+                    strokeWidth,
+                    StrokeCap.round
+                )
+            },
+            { canvas ->
+                canvas.drawLine(start, end, Paint().apply {
+                    this.color = Color.Cyan
+                    this.strokeWidth = strokeWidth
+                    this.strokeCap = StrokeCap.round
+                })
+            }
+        )
+
+        // ... now test that Brush parameters are also rendered with the correct stroke parameters
+        testDrawScopeAndCanvasAreEquivalent(
+            width,
+            height,
+            {
+                drawLine(
+                    SolidColor(Color.Cyan),
+                    start,
+                    end,
+                    strokeWidth,
+                    StrokeCap.round
+                )
+            },
+            { canvas ->
+                canvas.drawLine(start, end, Paint().apply {
+                    this.color = Color.Cyan
+                    this.strokeWidth = strokeWidth
+                    this.strokeCap = StrokeCap.round
+                })
+            }
+        )
+    }
+
+    @Test
+    fun testDrawPointStrokeParametersAreApplied() {
+        val width = 200
+        val height = 200
+        val points = listOf(
+            Offset.Zero,
+            Offset(10f, 10f),
+            Offset(25f, 25f),
+            Offset(40f, 40f),
+            Offset(50f, 50f),
+            Offset(75f, 75f),
+            Offset(150f, 150f)
+        )
+        // Test first that colors are rendered with the correct stroke parameters
+        testDrawScopeAndCanvasAreEquivalent(
+            width,
+            height,
+            {
+                drawPoints(
+                    points,
+                    PointMode.points,
+                    Color.Magenta,
+                    strokeWidth = 15.0f,
+                    cap = StrokeCap.butt
+                )
+            },
+            { canvas ->
+                canvas.drawPoints(
+                    PointMode.points,
+                    points,
+                    Paint().apply {
+                        this.color = Color.Magenta
+                        this.strokeWidth = 15.0f
+                        this.strokeCap = StrokeCap.butt
+                    }
+                )
+            }
+        )
+
+        // ... now verify that Brush parameters are also rendered with the correct stroke parameters
+        testDrawScopeAndCanvasAreEquivalent(
+            width,
+            height,
+            {
+                drawPoints(
+                    points,
+                    PointMode.points,
+                    SolidColor(Color.Magenta),
+                    strokeWidth = 15.0f,
+                    cap = StrokeCap.butt
+                )
+            },
+            { canvas ->
+                canvas.drawPoints(
+                    PointMode.points,
+                    points,
+                    Paint().apply {
+                        this.color = Color.Magenta
+                        this.strokeWidth = 15.0f
+                        this.strokeCap = StrokeCap.butt
+                    }
+                )
+            }
+        )
+    }
+
+    /**
+     * Helper method used  to confirm both DrawScope rendered content and Canvas drawn
+     * content are identical
+     */
+    private fun testDrawScopeAndCanvasAreEquivalent(
+        width: Int,
+        height: Int,
+        drawScopeBlock: DrawScope.() -> Unit,
+        canvasBlock: (Canvas) -> Unit
+    ) {
+        val size = Size(width.toFloat(), height.toFloat())
+        val imageAsset1 = ImageAsset(width, height)
+        TestDrawScope().drawInto(Canvas(imageAsset1), size) {
+            drawScopeBlock()
+        }
+
+        val imageAsset2 = ImageAsset(width, height)
+        canvasBlock(Canvas(imageAsset2))
+
+        val pixelMap1 = imageAsset1.toPixelMap()
+        val pixelMap2 = imageAsset2.toPixelMap()
+        assertEquals(pixelMap1.width, pixelMap2.width)
+        assertEquals(pixelMap1.height, pixelMap2.height)
+        assertEquals(pixelMap1.stride, pixelMap2.stride)
+        assertEquals(pixelMap1.bufferOffset, pixelMap2.bufferOffset)
+        for (x in 0 until pixelMap1.width) {
+            for (y in 0 until pixelMap1.height) {
+                assertEquals("coordinate: " + x + ", " + y + " expected: " +
+                        pixelMap1[x, y] + " actual: " + pixelMap2[x, y],
+                    pixelMap1[x, y],
+                    pixelMap2[x, y]
+                )
+            }
+        }
+    }
+
     class SaveCountCanvas(val canvas: Canvas) : Canvas by canvas {
 
         var saveCount: Int = 0
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 ab68b9c..c6419d9 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
@@ -21,7 +21,6 @@
 import androidx.ui.geometry.RRect
 import androidx.ui.geometry.Rect
 import androidx.ui.graphics.vectormath.degrees
-import java.lang.UnsupportedOperationException
 
 actual fun Path(): Path = AndroidPath()
 
@@ -70,16 +69,16 @@
                 }
         }
 
-    override fun moveTo(dx: Float, dy: Float) {
-        internalPath.moveTo(dx, dy)
+    override fun moveTo(x: Float, y: Float) {
+        internalPath.moveTo(x, y)
     }
 
     override fun relativeMoveTo(dx: Float, dy: Float) {
         internalPath.rMoveTo(dx, dy)
     }
 
-    override fun lineTo(dx: Float, dy: Float) {
-        internalPath.lineTo(dx, dy)
+    override fun lineTo(x: Float, y: Float) {
+        internalPath.lineTo(x, y)
     }
 
     override fun relativeLineTo(dx: Float, dy: Float) {
@@ -90,8 +89,8 @@
         internalPath.quadTo(x1, y1, x2, y2)
     }
 
-    override fun relativeQuadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float) {
-        internalPath.rQuadTo(x1, y1, x2, y2)
+    override fun relativeQuadraticBezierTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float) {
+        internalPath.rQuadTo(dx1, dy1, dx2, dy2)
     }
 
     override fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
@@ -102,11 +101,18 @@
         )
     }
 
-    override fun relativeCubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
+    override fun relativeCubicTo(
+        dx1: Float,
+        dy1: Float,
+        dx2: Float,
+        dy2: Float,
+        dx3: Float,
+        dy3: Float
+    ) {
         internalPath.rCubicTo(
-            x1, y1,
-            x2, y2,
-            x3, y3
+            dx1, dy1,
+            dx2, dy2,
+            dx3, dy3
         )
     }
 
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 cac643c..03a6827 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
@@ -55,7 +55,7 @@
     /**
      * Starts a new subpath at the given coordinate
      */
-    fun moveTo(dx: Float, dy: Float)
+    fun moveTo(x: Float, y: Float)
 
     /**
      * Starts a new subpath at the given offset from the current point
@@ -65,7 +65,7 @@
     /**
      * Adds a straight line segment from the current point to the given point
      */
-    fun lineTo(dx: Float, dy: Float)
+    fun lineTo(x: Float, y: Float)
 
     /**
      * Adds a straight line segment from the current point to the point
@@ -75,33 +75,33 @@
 
     /**
      * Adds a quadratic bezier segment that curves from the current
-     * point to the given point (x2,y2), using the control point
-     * (x1,y1).
+     * point to the given point ([x2], [y2]), using the control point
+     * ([x1], [y1]).
      */
     fun quadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float)
 
     /**
      * Adds a quadratic bezier segment that curves from the current
-     * point to the point at the offset (x2,y2) from the current point,
-     * using the control point at the offset (x1,y1) from the current
+     * point to the point at the offset ([dx2], [dy2]) from the current point,
+     * using the control point at the offset ([dx1], [dy1]) from the current
      * point.
      */
-    fun relativeQuadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float)
+    fun relativeQuadraticBezierTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float)
 
     /**
      * Adds a cubic bezier segment that curves from the current point
-     * to the given point (x3,y3), using the control points (x1,y1) and
-     * (x2,y2).
+     * to the given point ([x3], [y3]), using the control points ([x1], [y1]) and
+     * ([x2], [y2]).
      */
     fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)
 
     /**
      * Adds a cubic bezier segment that curves from the current point
-     * to the point at the offset (x3,y3) from the current point, using
-     * the control points at the offsets (x1,y1) and (x2,y2) from the
+     * to the point at the offset ([dx3], [dy3]) from the current point, using
+     * the control points at the offsets ([dx1], [dy1]) and ([dx2], [dy2]) from the
      * current point.
      */
-    fun relativeCubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)
+    fun relativeCubicTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float)
 
     /**
      * If the [forceMoveTo] argument is false, adds a straight line
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 7211201..4047908 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
@@ -1078,8 +1078,8 @@
             if (this.blendMode != blendMode) this.blendMode = blendMode
             if (this.strokeWidth != strokeWidth) this.strokeWidth = strokeWidth
             if (this.strokeMiterLimit != miter) this.strokeMiterLimit = miter
-            if (this.strokeCap != strokeCap) this.strokeCap = cap
-            if (this.strokeJoin != strokeJoin) this.strokeJoin = join
+            if (this.strokeCap != cap) this.strokeCap = cap
+            if (this.strokeJoin != join) this.strokeJoin = join
             this.asFrameworkPaint().setNativePathEffect(pathEffect)
         }
 
@@ -1103,8 +1103,8 @@
             if (this.blendMode != blendMode) this.blendMode = blendMode
             if (this.strokeWidth != strokeWidth) this.strokeWidth = strokeWidth
             if (this.strokeMiterLimit != miter) this.strokeMiterLimit = miter
-            if (this.strokeCap != strokeCap) this.strokeCap = cap
-            if (this.strokeJoin != strokeJoin) this.strokeJoin = join
+            if (this.strokeCap != cap) this.strokeCap = cap
+            if (this.strokeJoin != join) this.strokeJoin = join
             this.asFrameworkPaint().setNativePathEffect(pathEffect)
         }
 
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt
index 96c514a..031c47c 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt
@@ -26,19 +26,19 @@
 
     fun moveTo(x: Float, y: Float) = addNode(PathNode.MoveTo(x, y))
 
-    fun moveToRelative(x: Float, y: Float) = addNode(PathNode.RelativeMoveTo(x, y))
+    fun moveToRelative(dx: Float, dy: Float) = addNode(PathNode.RelativeMoveTo(dx, dy))
 
     fun lineTo(x: Float, y: Float) = addNode(PathNode.LineTo(x, y))
 
-    fun lineToRelative(x: Float, y: Float) = addNode(PathNode.RelativeLineTo(x, y))
+    fun lineToRelative(dx: Float, dy: Float) = addNode(PathNode.RelativeLineTo(dx, dy))
 
     fun horizontalLineTo(x: Float) = addNode(PathNode.HorizontalTo(x))
 
-    fun horizontalLineToRelative(x: Float) = addNode(PathNode.RelativeHorizontalTo(x))
+    fun horizontalLineToRelative(dx: Float) = addNode(PathNode.RelativeHorizontalTo(dx))
 
     fun verticalLineTo(y: Float) = addNode(PathNode.VerticalTo(y))
 
-    fun verticalLineToRelative(y: Float) = addNode(PathNode.RelativeVerticalTo(y))
+    fun verticalLineToRelative(dy: Float) = addNode(PathNode.RelativeVerticalTo(dy))
 
     fun curveTo(
         x1: Float,
@@ -61,20 +61,20 @@
     fun reflectiveCurveTo(x1: Float, y1: Float, x2: Float, y2: Float) =
         addNode(PathNode.ReflectiveCurveTo(x1, y1, x2, y2))
 
-    fun reflectiveCurveToRelative(x1: Float, y1: Float, x2: Float, y2: Float) =
-        addNode(PathNode.RelativeReflectiveCurveTo(x1, y1, x2, y2))
+    fun reflectiveCurveToRelative(dx1: Float, dy1: Float, dx2: Float, dy2: Float) =
+        addNode(PathNode.RelativeReflectiveCurveTo(dx1, dy1, dx2, dy2))
 
     fun quadTo(x1: Float, y1: Float, x2: Float, y2: Float) =
         addNode(PathNode.QuadTo(x1, y1, x2, y2))
 
-    fun quadToRelative(x1: Float, y1: Float, x2: Float, y2: Float) =
-        addNode(PathNode.RelativeQuadTo(x1, y1, x2, y2))
+    fun quadToRelative(dx1: Float, dy1: Float, dx2: Float, dy2: Float) =
+        addNode(PathNode.RelativeQuadTo(dx1, dy1, dx2, dy2))
 
     fun reflectiveQuadTo(x1: Float, y1: Float) =
         addNode(PathNode.ReflectiveQuadTo(x1, y1))
 
-    fun reflectiveQuadToRelative(x1: Float, y1: Float) =
-        addNode(PathNode.RelativeReflectiveQuadTo(x1, y1))
+    fun reflectiveQuadToRelative(dx1: Float, dy1: Float) =
+        addNode(PathNode.RelativeReflectiveQuadTo(dx1, dy1))
 
     fun arcTo(
         horizontalEllipseRadius: Float,
@@ -102,9 +102,9 @@
         theta: Float,
         isMoreThanHalf: Boolean,
         isPositiveArc: Boolean,
-        x1: Float,
-        y1: Float
-    ) = addNode(PathNode.RelativeArcTo(a, b, theta, isMoreThanHalf, isPositiveArc, x1, y1))
+        dx1: Float,
+        dy1: Float
+    ) = addNode(PathNode.RelativeArcTo(a, b, theta, isMoreThanHalf, isPositiveArc, dx1, dy1))
 
     private fun addNode(node: PathNode): PathBuilder {
         nodes.add(node)
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt
index e2bb858..319b14f 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt
@@ -27,16 +27,16 @@
     // for simplicity and to make equals comparisons robust.
     object Close : PathNode()
 
-    data class RelativeMoveTo(val x: Float, val y: Float) : PathNode()
+    data class RelativeMoveTo(val dx: Float, val dy: Float) : PathNode()
     data class MoveTo(val x: Float, val y: Float) : PathNode()
 
-    data class RelativeLineTo(val x: Float, val y: Float) : PathNode()
+    data class RelativeLineTo(val dx: Float, val dy: Float) : PathNode()
     data class LineTo(val x: Float, val y: Float) : PathNode()
 
-    data class RelativeHorizontalTo(val x: Float) : PathNode()
+    data class RelativeHorizontalTo(val dx: Float) : PathNode()
     data class HorizontalTo(val x: Float) : PathNode()
 
-    data class RelativeVerticalTo(val y: Float) : PathNode()
+    data class RelativeVerticalTo(val dy: Float) : PathNode()
     data class VerticalTo(val y: Float) : PathNode()
 
     data class RelativeCurveTo(
@@ -58,10 +58,10 @@
     ) : PathNode(isCurve = true)
 
     data class RelativeReflectiveCurveTo(
-        val x1: Float,
-        val y1: Float,
-        val x2: Float,
-        val y2: Float
+        val dx1: Float,
+        val dy1: Float,
+        val dx2: Float,
+        val dy2: Float
     ) : PathNode(isCurve = true)
 
     data class ReflectiveCurveTo(
@@ -72,10 +72,10 @@
     ) : PathNode(isCurve = true)
 
     data class RelativeQuadTo(
-        val x1: Float,
-        val y1: Float,
-        val x2: Float,
-        val y2: Float
+        val dx1: Float,
+        val dy1: Float,
+        val dx2: Float,
+        val dy2: Float
     ) : PathNode(isQuad = true)
 
     data class QuadTo(
@@ -86,8 +86,8 @@
     ) : PathNode(isQuad = true)
 
     data class RelativeReflectiveQuadTo(
-        val x: Float,
-        val y: Float
+        val dx: Float,
+        val dy: Float
     ) : PathNode(isQuad = true)
 
     data class ReflectiveQuadTo(
@@ -125,7 +125,7 @@
 internal fun Char.toPathNodes(args: FloatArray): List<PathNode> = when (this) {
     RelativeCloseKey, CloseKey -> listOf(PathNode.Close)
     RelativeMoveToKey -> pathNodesFromArgs(args, NUM_MOVE_TO_ARGS) { array ->
-        PathNode.RelativeMoveTo(x = array[0], y = array[1])
+        PathNode.RelativeMoveTo(dx = array[0], dy = array[1])
     }
 
     MoveToKey -> pathNodesFromArgs(args, NUM_MOVE_TO_ARGS) { array ->
@@ -133,7 +133,7 @@
     }
 
     RelativeLineToKey -> pathNodesFromArgs(args, NUM_LINE_TO_ARGS) { array ->
-        PathNode.RelativeLineTo(x = array[0], y = array[1])
+        PathNode.RelativeLineTo(dx = array[0], dy = array[1])
     }
 
     LineToKey -> pathNodesFromArgs(args, NUM_LINE_TO_ARGS) { array ->
@@ -141,7 +141,7 @@
     }
 
     RelativeHorizontalToKey -> pathNodesFromArgs(args, NUM_HORIZONTAL_TO_ARGS) { array ->
-        PathNode.RelativeHorizontalTo(x = array[0])
+        PathNode.RelativeHorizontalTo(dx = array[0])
     }
 
     HorizontalToKey -> pathNodesFromArgs(args, NUM_HORIZONTAL_TO_ARGS) { array ->
@@ -149,7 +149,7 @@
     }
 
     RelativeVerticalToKey -> pathNodesFromArgs(args, NUM_VERTICAL_TO_ARGS) { array ->
-        PathNode.RelativeVerticalTo(y = array[0])
+        PathNode.RelativeVerticalTo(dy = array[0])
     }
 
     VerticalToKey -> pathNodesFromArgs(args, NUM_VERTICAL_TO_ARGS) { array ->
@@ -180,10 +180,10 @@
 
     RelativeReflectiveCurveToKey -> pathNodesFromArgs(args, NUM_REFLECTIVE_CURVE_TO_ARGS) { array ->
         PathNode.RelativeReflectiveCurveTo(
-            x1 = array[0],
-            y1 = array[1],
-            x2 = array[2],
-            y2 = array[3]
+            dx1 = array[0],
+            dy1 = array[1],
+            dx2 = array[2],
+            dy2 = array[3]
         )
     }
 
@@ -198,10 +198,10 @@
 
     RelativeQuadToKey -> pathNodesFromArgs(args, NUM_QUAD_TO_ARGS) { array ->
         PathNode.RelativeQuadTo(
-            x1 = array[0],
-            y1 = array[1],
-            x2 = array[2],
-            y2 = array[3]
+            dx1 = array[0],
+            dy1 = array[1],
+            dx2 = array[2],
+            dy2 = array[3]
         )
     }
 
@@ -215,7 +215,7 @@
     }
 
     RelativeReflectiveQuadToKey -> pathNodesFromArgs(args, NUM_REFLECTIVE_QUAD_TO_ARGS) { array ->
-        PathNode.RelativeReflectiveQuadTo(x = array[0], y = array[1])
+        PathNode.RelativeReflectiveQuadTo(dx = array[0], dy = array[1])
     }
 
     ReflectiveQuadToKey -> pathNodesFromArgs(args, NUM_REFLECTIVE_QUAD_TO_ARGS) { array ->
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt
index 84e299b..4de210b 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt
@@ -152,9 +152,9 @@
     }
 
     private fun RelativeMoveTo.relativeMoveTo(target: Path) {
-        currentPoint.x += x
-        currentPoint.y += y
-        target.relativeMoveTo(x, y)
+        currentPoint.x += dx
+        currentPoint.y += dy
+        target.relativeMoveTo(dx, dy)
         segmentPoint.x = currentPoint.x
         segmentPoint.y = currentPoint.y
     }
@@ -168,9 +168,9 @@
     }
 
     private fun RelativeLineTo.relativeLineTo(target: Path) {
-        target.relativeLineTo(x, y)
-        currentPoint.x += x
-        currentPoint.y += y
+        target.relativeLineTo(dx, dy)
+        currentPoint.x += dx
+        currentPoint.y += dy
     }
 
     private fun LineTo.lineTo(target: Path) {
@@ -180,8 +180,8 @@
     }
 
     private fun RelativeHorizontalTo.relativeHorizontalTo(target: Path) {
-        target.relativeLineTo(x, 0.0f)
-        currentPoint.x += x
+        target.relativeLineTo(dx, 0.0f)
+        currentPoint.x += dx
     }
 
     private fun HorizontalTo.horizontalTo(target: Path) {
@@ -190,8 +190,8 @@
     }
 
     private fun RelativeVerticalTo.relativeVerticalTo(target: Path) {
-        target.relativeLineTo(0.0f, y)
-        currentPoint.y += y
+        target.relativeLineTo(0.0f, dy)
+        currentPoint.y += dy
     }
 
     private fun VerticalTo.verticalTo(target: Path) {
@@ -236,13 +236,13 @@
 
         target.relativeCubicTo(
             reflectiveCtrlPoint.x, reflectiveCtrlPoint.y,
-            x1, y1,
-            x2, y2
+            dx1, dy1,
+            dx2, dy2
         )
-        ctrlPoint.x = currentPoint.x + x1
-        ctrlPoint.y = currentPoint.y + y1
-        currentPoint.x += x2
-        currentPoint.y += y2
+        ctrlPoint.x = currentPoint.x + dx1
+        ctrlPoint.y = currentPoint.y + dy1
+        currentPoint.x += dx2
+        currentPoint.y += dy2
     }
 
     private fun ReflectiveCurveTo.reflectiveCurveTo(prevIsCurve: Boolean, target: Path) {
@@ -265,11 +265,11 @@
     }
 
     private fun RelativeQuadTo.relativeQuadTo(target: Path) {
-        target.relativeQuadraticBezierTo(x1, y1, x2, y2)
-        ctrlPoint.x = currentPoint.x + x1
-        ctrlPoint.y = currentPoint.y + y1
-        currentPoint.x += x1
-        currentPoint.y += y1
+        target.relativeQuadraticBezierTo(dx1, dy1, dx2, dy2)
+        ctrlPoint.x = currentPoint.x + dx1
+        ctrlPoint.y = currentPoint.y + dy1
+        currentPoint.x += dx1
+        currentPoint.y += dy1
     }
 
     private fun QuadTo.quadTo(target: Path) {
@@ -293,12 +293,12 @@
 
         target.relativeQuadraticBezierTo(
             reflectiveCtrlPoint.x,
-            reflectiveCtrlPoint.y, x, y
+            reflectiveCtrlPoint.y, dx, dy
         )
         ctrlPoint.x = currentPoint.x + reflectiveCtrlPoint.x
         ctrlPoint.y = currentPoint.y + reflectiveCtrlPoint.y
-        currentPoint.x += x
-        currentPoint.y += y
+        currentPoint.x += dx
+        currentPoint.y += dy
     }
 
     private fun ReflectiveQuadTo.reflectiveQuadTo(prevIsQuad: Boolean, target: Path) {
diff --git a/ui/ui-layout/api/0.1.0-dev15.txt b/ui/ui-layout/api/0.1.0-dev15.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/0.1.0-dev15.txt
+++ b/ui/ui-layout/api/0.1.0-dev15.txt
@@ -8,22 +8,22 @@
 
   @androidx.compose.Immutable public interface Arrangement {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
   }
 
   public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
   }
 
   public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
   }
 
   public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.End INSTANCE;
   }
 
   public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
 
   public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
   }
 
   public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
   }
 
   public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
   }
 
   public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
   }
 
   public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
   }
 
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
   public final class ChainStyle {
-    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+    field public static final androidx.ui.layout.ChainStyle.Companion Companion;
   }
 
   public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+    field public static final androidx.ui.layout.ColumnScope INSTANCE;
   }
 
   @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
-    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
-    field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+    field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
   }
 
   public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
   }
 
   public interface Dimension {
-    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+    field public static final androidx.ui.layout.Dimension.Companion Companion;
   }
 
   public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
     method public float getMaxWidth();
     method public float getMinHeight();
     method public float getMinWidth();
-    field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+    field public static final androidx.ui.layout.DpConstraints.Companion Companion;
   }
 
   public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
   }
 
   public enum FlowCrossAxisAlignment {
+    method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
   }
 
   public enum IntrinsicSize {
+    method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.IntrinsicSize[] values();
     enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
     enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
   }
@@ -581,6 +585,8 @@
   }
 
   public enum MainAxisAlignment {
+    method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.MainAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.RowScope! INSTANCE;
+    field public static final androidx.ui.layout.RowScope INSTANCE;
   }
 
   public enum SizeMode {
+    method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.SizeMode[] values();
     enum_constant public static final androidx.ui.layout.SizeMode Expand;
     enum_constant public static final androidx.ui.layout.SizeMode Wrap;
   }
diff --git a/ui/ui-layout/api/current.txt b/ui/ui-layout/api/current.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/current.txt
+++ b/ui/ui-layout/api/current.txt
@@ -8,22 +8,22 @@
 
   @androidx.compose.Immutable public interface Arrangement {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
   }
 
   public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
   }
 
   public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
   }
 
   public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.End INSTANCE;
   }
 
   public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
 
   public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
   }
 
   public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
   }
 
   public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
   }
 
   public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
   }
 
   public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
   }
 
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
   public final class ChainStyle {
-    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+    field public static final androidx.ui.layout.ChainStyle.Companion Companion;
   }
 
   public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+    field public static final androidx.ui.layout.ColumnScope INSTANCE;
   }
 
   @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
-    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
-    field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+    field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
   }
 
   public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
   }
 
   public interface Dimension {
-    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+    field public static final androidx.ui.layout.Dimension.Companion Companion;
   }
 
   public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
     method public float getMaxWidth();
     method public float getMinHeight();
     method public float getMinWidth();
-    field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+    field public static final androidx.ui.layout.DpConstraints.Companion Companion;
   }
 
   public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
   }
 
   public enum FlowCrossAxisAlignment {
+    method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
   }
 
   public enum IntrinsicSize {
+    method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.IntrinsicSize[] values();
     enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
     enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
   }
@@ -581,6 +585,8 @@
   }
 
   public enum MainAxisAlignment {
+    method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.MainAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.RowScope! INSTANCE;
+    field public static final androidx.ui.layout.RowScope INSTANCE;
   }
 
   public enum SizeMode {
+    method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.SizeMode[] values();
     enum_constant public static final androidx.ui.layout.SizeMode Expand;
     enum_constant public static final androidx.ui.layout.SizeMode Wrap;
   }
diff --git a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt
@@ -8,22 +8,22 @@
 
   @androidx.compose.Immutable public interface Arrangement {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
   }
 
   public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
   }
 
   public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
   }
 
   public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.End INSTANCE;
   }
 
   public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
 
   public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
   }
 
   public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
   }
 
   public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
   }
 
   public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
   }
 
   public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
   }
 
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
   public final class ChainStyle {
-    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+    field public static final androidx.ui.layout.ChainStyle.Companion Companion;
   }
 
   public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+    field public static final androidx.ui.layout.ColumnScope INSTANCE;
   }
 
   @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
-    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
-    field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+    field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
   }
 
   public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
   }
 
   public interface Dimension {
-    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+    field public static final androidx.ui.layout.Dimension.Companion Companion;
   }
 
   public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
     method public float getMaxWidth();
     method public float getMinHeight();
     method public float getMinWidth();
-    field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+    field public static final androidx.ui.layout.DpConstraints.Companion Companion;
   }
 
   public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
   }
 
   public enum FlowCrossAxisAlignment {
+    method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
   }
 
   public enum IntrinsicSize {
+    method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.IntrinsicSize[] values();
     enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
     enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
   }
@@ -581,6 +585,8 @@
   }
 
   public enum MainAxisAlignment {
+    method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.MainAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.RowScope! INSTANCE;
+    field public static final androidx.ui.layout.RowScope INSTANCE;
   }
 
   public enum SizeMode {
+    method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.SizeMode[] values();
     enum_constant public static final androidx.ui.layout.SizeMode Expand;
     enum_constant public static final androidx.ui.layout.SizeMode Wrap;
   }
diff --git a/ui/ui-layout/api/public_plus_experimental_current.txt b/ui/ui-layout/api/public_plus_experimental_current.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/public_plus_experimental_current.txt
+++ b/ui/ui-layout/api/public_plus_experimental_current.txt
@@ -8,22 +8,22 @@
 
   @androidx.compose.Immutable public interface Arrangement {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
   }
 
   public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
   }
 
   public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
   }
 
   public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.End INSTANCE;
   }
 
   public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
 
   public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
   }
 
   public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
   }
 
   public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
   }
 
   public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
   }
 
   public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
   }
 
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
   public final class ChainStyle {
-    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+    field public static final androidx.ui.layout.ChainStyle.Companion Companion;
   }
 
   public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+    field public static final androidx.ui.layout.ColumnScope INSTANCE;
   }
 
   @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
-    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
-    field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+    field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
   }
 
   public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
   }
 
   public interface Dimension {
-    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+    field public static final androidx.ui.layout.Dimension.Companion Companion;
   }
 
   public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
     method public float getMaxWidth();
     method public float getMinHeight();
     method public float getMinWidth();
-    field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+    field public static final androidx.ui.layout.DpConstraints.Companion Companion;
   }
 
   public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
   }
 
   public enum FlowCrossAxisAlignment {
+    method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
   }
 
   public enum IntrinsicSize {
+    method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.IntrinsicSize[] values();
     enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
     enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
   }
@@ -581,6 +585,8 @@
   }
 
   public enum MainAxisAlignment {
+    method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.MainAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.RowScope! INSTANCE;
+    field public static final androidx.ui.layout.RowScope INSTANCE;
   }
 
   public enum SizeMode {
+    method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.SizeMode[] values();
     enum_constant public static final androidx.ui.layout.SizeMode Expand;
     enum_constant public static final androidx.ui.layout.SizeMode Wrap;
   }
diff --git a/ui/ui-layout/api/restricted_0.1.0-dev15.txt b/ui/ui-layout/api/restricted_0.1.0-dev15.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-layout/api/restricted_0.1.0-dev15.txt
@@ -8,22 +8,22 @@
 
   @androidx.compose.Immutable public interface Arrangement {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
   }
 
   public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
   }
 
   public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
   }
 
   public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.End INSTANCE;
   }
 
   public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
 
   public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
   }
 
   public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
   }
 
   public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
   }
 
   public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
   }
 
   public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
   }
 
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
   public final class ChainStyle {
-    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+    field public static final androidx.ui.layout.ChainStyle.Companion Companion;
   }
 
   public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+    field public static final androidx.ui.layout.ColumnScope INSTANCE;
   }
 
   @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
-    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
-    field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+    field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
   }
 
   public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
   }
 
   public interface Dimension {
-    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+    field public static final androidx.ui.layout.Dimension.Companion Companion;
   }
 
   public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
     method public float getMaxWidth();
     method public float getMinHeight();
     method public float getMinWidth();
-    field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+    field public static final androidx.ui.layout.DpConstraints.Companion Companion;
   }
 
   public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
   }
 
   public enum FlowCrossAxisAlignment {
+    method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
   }
 
   public enum IntrinsicSize {
+    method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.IntrinsicSize[] values();
     enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
     enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
   }
@@ -581,6 +585,8 @@
   }
 
   public enum MainAxisAlignment {
+    method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.MainAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.RowScope! INSTANCE;
+    field public static final androidx.ui.layout.RowScope INSTANCE;
   }
 
   public enum SizeMode {
+    method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.SizeMode[] values();
     enum_constant public static final androidx.ui.layout.SizeMode Expand;
     enum_constant public static final androidx.ui.layout.SizeMode Wrap;
   }
diff --git a/ui/ui-layout/api/restricted_current.txt b/ui/ui-layout/api/restricted_current.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/restricted_current.txt
+++ b/ui/ui-layout/api/restricted_current.txt
@@ -8,22 +8,22 @@
 
   @androidx.compose.Immutable public interface Arrangement {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
   }
 
   public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
   }
 
   public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
   }
 
   public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.End INSTANCE;
   }
 
   public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
 
   public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
   }
 
   public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
   }
 
   public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
   }
 
   public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
   }
 
   public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
     method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
-    field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+    field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
   }
 
   public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
   }
 
   public final class ChainStyle {
-    field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+    field public static final androidx.ui.layout.ChainStyle.Companion Companion;
   }
 
   public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+    field public static final androidx.ui.layout.ColumnScope INSTANCE;
   }
 
   @androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
-    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+    field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
   }
 
   @Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
   }
 
   @androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
-    field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+    field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
   }
 
   public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
   }
 
   public interface Dimension {
-    field public static final androidx.ui.layout.Dimension.Companion! Companion;
+    field public static final androidx.ui.layout.Dimension.Companion Companion;
   }
 
   public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
     method public float getMaxWidth();
     method public float getMinHeight();
     method public float getMinWidth();
-    field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+    field public static final androidx.ui.layout.DpConstraints.Companion Companion;
   }
 
   public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
   }
 
   public enum FlowCrossAxisAlignment {
+    method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
     enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
   }
 
   public enum IntrinsicSize {
+    method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.IntrinsicSize[] values();
     enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
     enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
   }
@@ -581,6 +585,8 @@
   }
 
   public enum MainAxisAlignment {
+    method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.MainAxisAlignment[] values();
     enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
     enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
     method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
     method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
     method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
-    field public static final androidx.ui.layout.RowScope! INSTANCE;
+    field public static final androidx.ui.layout.RowScope INSTANCE;
   }
 
   public enum SizeMode {
+    method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.layout.SizeMode[] values();
     enum_constant public static final androidx.ui.layout.SizeMode Expand;
     enum_constant public static final androidx.ui.layout.SizeMode Wrap;
   }
diff --git a/ui/ui-material/api/0.1.0-dev15.txt b/ui/ui-material/api/0.1.0-dev15.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/0.1.0-dev15.txt
+++ b/ui/ui-material/api/0.1.0-dev15.txt
@@ -2,6 +2,8 @@
 package androidx.ui.material {
 
   public enum AlertDialogButtonLayout {
+    method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.AlertDialogButtonLayout[] values();
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
   }
@@ -33,7 +35,7 @@
     property public final float DefaultMinWidth;
     property public final long defaultDisabledBackgroundColor;
     property public final long defaultDisabledContentColor;
-    field public static final androidx.ui.material.Button! INSTANCE;
+    field public static final androidx.ui.material.Button INSTANCE;
   }
 
   public final class ButtonKt {
@@ -94,7 +96,7 @@
   public final class DrawerConstants {
     method public float getDefaultElevation();
     property public final float DefaultElevation;
-    field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+    field public static final androidx.ui.material.DrawerConstants INSTANCE;
   }
 
   public final class DrawerKt {
@@ -103,6 +105,8 @@
   }
 
   public enum DrawerState {
+    method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.DrawerState[] values();
     enum_constant public static final androidx.ui.material.DrawerState Closed;
     enum_constant public static final androidx.ui.material.DrawerState Opened;
   }
@@ -147,7 +151,7 @@
     property public final androidx.ui.material.ColorPalette colors;
     property public final androidx.ui.material.Shapes shapes;
     property public final androidx.ui.material.Typography typography;
-    field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+    field public static final androidx.ui.material.MaterialTheme INSTANCE;
   }
 
   public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
   public final class ProgressIndicatorConstants {
     method public float getDefaultStrokeWidth();
     property public final float DefaultStrokeWidth;
-    field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+    field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
   }
 
   public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
     method public long getDefaultUnselectedColor();
     property public final long defaultDisabledColor;
     property public final long defaultUnselectedColor;
-    field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+    field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
   }
 
   public final class RadioButtonKt {
@@ -192,10 +196,12 @@
   }
 
   public final class Scaffold {
-    field public static final androidx.ui.material.Scaffold! INSTANCE;
+    field public static final androidx.ui.material.Scaffold INSTANCE;
   }
 
   public enum Scaffold.FabPosition {
+    method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.Scaffold.FabPosition[] values();
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
   }
@@ -267,7 +273,7 @@
   public final class TabRow {
     method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
     method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
-    field public static final androidx.ui.material.TabRow! INSTANCE;
+    field public static final androidx.ui.material.TabRow INSTANCE;
   }
 
   @androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
   public final class TextButton {
     method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
     property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
-    field public static final androidx.ui.material.TextButton! INSTANCE;
+    field public static final androidx.ui.material.TextButton INSTANCE;
   }
 
   public final class TextFieldKt {
diff --git a/ui/ui-material/api/api_lint.ignore b/ui/ui-material/api/api_lint.ignore
deleted file mode 100644
index 7e1573a..0000000
--- a/ui/ui-material/api/api_lint.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-NotCloseable: androidx.ui.material.ripple.RippleEffect:
-    Classes that release resources (finish()) should implement AutoClosable and CloseGuard: class androidx.ui.material.ripple.RippleEffect
diff --git a/ui/ui-material/api/current.txt b/ui/ui-material/api/current.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/current.txt
+++ b/ui/ui-material/api/current.txt
@@ -2,6 +2,8 @@
 package androidx.ui.material {
 
   public enum AlertDialogButtonLayout {
+    method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.AlertDialogButtonLayout[] values();
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
   }
@@ -33,7 +35,7 @@
     property public final float DefaultMinWidth;
     property public final long defaultDisabledBackgroundColor;
     property public final long defaultDisabledContentColor;
-    field public static final androidx.ui.material.Button! INSTANCE;
+    field public static final androidx.ui.material.Button INSTANCE;
   }
 
   public final class ButtonKt {
@@ -94,7 +96,7 @@
   public final class DrawerConstants {
     method public float getDefaultElevation();
     property public final float DefaultElevation;
-    field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+    field public static final androidx.ui.material.DrawerConstants INSTANCE;
   }
 
   public final class DrawerKt {
@@ -103,6 +105,8 @@
   }
 
   public enum DrawerState {
+    method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.DrawerState[] values();
     enum_constant public static final androidx.ui.material.DrawerState Closed;
     enum_constant public static final androidx.ui.material.DrawerState Opened;
   }
@@ -147,7 +151,7 @@
     property public final androidx.ui.material.ColorPalette colors;
     property public final androidx.ui.material.Shapes shapes;
     property public final androidx.ui.material.Typography typography;
-    field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+    field public static final androidx.ui.material.MaterialTheme INSTANCE;
   }
 
   public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
   public final class ProgressIndicatorConstants {
     method public float getDefaultStrokeWidth();
     property public final float DefaultStrokeWidth;
-    field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+    field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
   }
 
   public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
     method public long getDefaultUnselectedColor();
     property public final long defaultDisabledColor;
     property public final long defaultUnselectedColor;
-    field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+    field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
   }
 
   public final class RadioButtonKt {
@@ -192,10 +196,12 @@
   }
 
   public final class Scaffold {
-    field public static final androidx.ui.material.Scaffold! INSTANCE;
+    field public static final androidx.ui.material.Scaffold INSTANCE;
   }
 
   public enum Scaffold.FabPosition {
+    method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.Scaffold.FabPosition[] values();
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
   }
@@ -267,7 +273,7 @@
   public final class TabRow {
     method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
     method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
-    field public static final androidx.ui.material.TabRow! INSTANCE;
+    field public static final androidx.ui.material.TabRow INSTANCE;
   }
 
   @androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
   public final class TextButton {
     method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
     property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
-    field public static final androidx.ui.material.TextButton! INSTANCE;
+    field public static final androidx.ui.material.TextButton INSTANCE;
   }
 
   public final class TextFieldKt {
diff --git a/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt
@@ -2,6 +2,8 @@
 package androidx.ui.material {
 
   public enum AlertDialogButtonLayout {
+    method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.AlertDialogButtonLayout[] values();
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
   }
@@ -33,7 +35,7 @@
     property public final float DefaultMinWidth;
     property public final long defaultDisabledBackgroundColor;
     property public final long defaultDisabledContentColor;
-    field public static final androidx.ui.material.Button! INSTANCE;
+    field public static final androidx.ui.material.Button INSTANCE;
   }
 
   public final class ButtonKt {
@@ -94,7 +96,7 @@
   public final class DrawerConstants {
     method public float getDefaultElevation();
     property public final float DefaultElevation;
-    field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+    field public static final androidx.ui.material.DrawerConstants INSTANCE;
   }
 
   public final class DrawerKt {
@@ -103,6 +105,8 @@
   }
 
   public enum DrawerState {
+    method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.DrawerState[] values();
     enum_constant public static final androidx.ui.material.DrawerState Closed;
     enum_constant public static final androidx.ui.material.DrawerState Opened;
   }
@@ -147,7 +151,7 @@
     property public final androidx.ui.material.ColorPalette colors;
     property public final androidx.ui.material.Shapes shapes;
     property public final androidx.ui.material.Typography typography;
-    field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+    field public static final androidx.ui.material.MaterialTheme INSTANCE;
   }
 
   public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
   public final class ProgressIndicatorConstants {
     method public float getDefaultStrokeWidth();
     property public final float DefaultStrokeWidth;
-    field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+    field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
   }
 
   public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
     method public long getDefaultUnselectedColor();
     property public final long defaultDisabledColor;
     property public final long defaultUnselectedColor;
-    field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+    field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
   }
 
   public final class RadioButtonKt {
@@ -192,10 +196,12 @@
   }
 
   public final class Scaffold {
-    field public static final androidx.ui.material.Scaffold! INSTANCE;
+    field public static final androidx.ui.material.Scaffold INSTANCE;
   }
 
   public enum Scaffold.FabPosition {
+    method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.Scaffold.FabPosition[] values();
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
   }
@@ -267,7 +273,7 @@
   public final class TabRow {
     method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
     method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
-    field public static final androidx.ui.material.TabRow! INSTANCE;
+    field public static final androidx.ui.material.TabRow INSTANCE;
   }
 
   @androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
   public final class TextButton {
     method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
     property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
-    field public static final androidx.ui.material.TextButton! INSTANCE;
+    field public static final androidx.ui.material.TextButton INSTANCE;
   }
 
   public final class TextFieldKt {
diff --git a/ui/ui-material/api/public_plus_experimental_current.txt b/ui/ui-material/api/public_plus_experimental_current.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/api/public_plus_experimental_current.txt
@@ -2,6 +2,8 @@
 package androidx.ui.material {
 
   public enum AlertDialogButtonLayout {
+    method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.AlertDialogButtonLayout[] values();
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
   }
@@ -33,7 +35,7 @@
     property public final float DefaultMinWidth;
     property public final long defaultDisabledBackgroundColor;
     property public final long defaultDisabledContentColor;
-    field public static final androidx.ui.material.Button! INSTANCE;
+    field public static final androidx.ui.material.Button INSTANCE;
   }
 
   public final class ButtonKt {
@@ -94,7 +96,7 @@
   public final class DrawerConstants {
     method public float getDefaultElevation();
     property public final float DefaultElevation;
-    field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+    field public static final androidx.ui.material.DrawerConstants INSTANCE;
   }
 
   public final class DrawerKt {
@@ -103,6 +105,8 @@
   }
 
   public enum DrawerState {
+    method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.DrawerState[] values();
     enum_constant public static final androidx.ui.material.DrawerState Closed;
     enum_constant public static final androidx.ui.material.DrawerState Opened;
   }
@@ -147,7 +151,7 @@
     property public final androidx.ui.material.ColorPalette colors;
     property public final androidx.ui.material.Shapes shapes;
     property public final androidx.ui.material.Typography typography;
-    field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+    field public static final androidx.ui.material.MaterialTheme INSTANCE;
   }
 
   public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
   public final class ProgressIndicatorConstants {
     method public float getDefaultStrokeWidth();
     property public final float DefaultStrokeWidth;
-    field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+    field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
   }
 
   public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
     method public long getDefaultUnselectedColor();
     property public final long defaultDisabledColor;
     property public final long defaultUnselectedColor;
-    field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+    field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
   }
 
   public final class RadioButtonKt {
@@ -192,10 +196,12 @@
   }
 
   public final class Scaffold {
-    field public static final androidx.ui.material.Scaffold! INSTANCE;
+    field public static final androidx.ui.material.Scaffold INSTANCE;
   }
 
   public enum Scaffold.FabPosition {
+    method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.Scaffold.FabPosition[] values();
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
   }
@@ -267,7 +273,7 @@
   public final class TabRow {
     method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
     method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
-    field public static final androidx.ui.material.TabRow! INSTANCE;
+    field public static final androidx.ui.material.TabRow INSTANCE;
   }
 
   @androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
   public final class TextButton {
     method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
     property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
-    field public static final androidx.ui.material.TextButton! INSTANCE;
+    field public static final androidx.ui.material.TextButton INSTANCE;
   }
 
   public final class TextFieldKt {
diff --git a/ui/ui-material/api/restricted_0.1.0-dev15.txt b/ui/ui-material/api/restricted_0.1.0-dev15.txt
index 392ee62..798e755 100644
--- a/ui/ui-material/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-material/api/restricted_0.1.0-dev15.txt
@@ -2,6 +2,8 @@
 package androidx.ui.material {
 
   public enum AlertDialogButtonLayout {
+    method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.AlertDialogButtonLayout[] values();
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
   }
@@ -33,7 +35,7 @@
     property public final float DefaultMinWidth;
     property public final long defaultDisabledBackgroundColor;
     property public final long defaultDisabledContentColor;
-    field public static final androidx.ui.material.Button! INSTANCE;
+    field public static final androidx.ui.material.Button INSTANCE;
   }
 
   public final class ButtonKt {
@@ -95,7 +97,7 @@
   public final class DrawerConstants {
     method public float getDefaultElevation();
     property public final float DefaultElevation;
-    field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+    field public static final androidx.ui.material.DrawerConstants INSTANCE;
   }
 
   public final class DrawerKt {
@@ -104,6 +106,8 @@
   }
 
   public enum DrawerState {
+    method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.DrawerState[] values();
     enum_constant public static final androidx.ui.material.DrawerState Closed;
     enum_constant public static final androidx.ui.material.DrawerState Opened;
   }
@@ -148,7 +152,7 @@
     property public final androidx.ui.material.ColorPalette colors;
     property public final androidx.ui.material.Shapes shapes;
     property public final androidx.ui.material.Typography typography;
-    field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+    field public static final androidx.ui.material.MaterialTheme INSTANCE;
   }
 
   public final class MaterialThemeKt {
@@ -163,7 +167,7 @@
   public final class ProgressIndicatorConstants {
     method public float getDefaultStrokeWidth();
     property public final float DefaultStrokeWidth;
-    field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+    field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
   }
 
   public final class ProgressIndicatorKt {
@@ -178,7 +182,7 @@
     method public long getDefaultUnselectedColor();
     property public final long defaultDisabledColor;
     property public final long defaultUnselectedColor;
-    field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+    field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
   }
 
   public final class RadioButtonKt {
@@ -193,10 +197,12 @@
   }
 
   public final class Scaffold {
-    field public static final androidx.ui.material.Scaffold! INSTANCE;
+    field public static final androidx.ui.material.Scaffold INSTANCE;
   }
 
   public enum Scaffold.FabPosition {
+    method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.Scaffold.FabPosition[] values();
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
   }
@@ -268,7 +274,7 @@
   public final class TabRow {
     method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
     method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
-    field public static final androidx.ui.material.TabRow! INSTANCE;
+    field public static final androidx.ui.material.TabRow INSTANCE;
   }
 
   @androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -284,7 +290,7 @@
   public final class TextButton {
     method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
     property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
-    field public static final androidx.ui.material.TextButton! INSTANCE;
+    field public static final androidx.ui.material.TextButton INSTANCE;
   }
 
   public final class TextFieldKt {
diff --git a/ui/ui-material/api/restricted_current.txt b/ui/ui-material/api/restricted_current.txt
index 392ee62..798e755 100644
--- a/ui/ui-material/api/restricted_current.txt
+++ b/ui/ui-material/api/restricted_current.txt
@@ -2,6 +2,8 @@
 package androidx.ui.material {
 
   public enum AlertDialogButtonLayout {
+    method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.AlertDialogButtonLayout[] values();
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
     enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
   }
@@ -33,7 +35,7 @@
     property public final float DefaultMinWidth;
     property public final long defaultDisabledBackgroundColor;
     property public final long defaultDisabledContentColor;
-    field public static final androidx.ui.material.Button! INSTANCE;
+    field public static final androidx.ui.material.Button INSTANCE;
   }
 
   public final class ButtonKt {
@@ -95,7 +97,7 @@
   public final class DrawerConstants {
     method public float getDefaultElevation();
     property public final float DefaultElevation;
-    field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+    field public static final androidx.ui.material.DrawerConstants INSTANCE;
   }
 
   public final class DrawerKt {
@@ -104,6 +106,8 @@
   }
 
   public enum DrawerState {
+    method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.DrawerState[] values();
     enum_constant public static final androidx.ui.material.DrawerState Closed;
     enum_constant public static final androidx.ui.material.DrawerState Opened;
   }
@@ -148,7 +152,7 @@
     property public final androidx.ui.material.ColorPalette colors;
     property public final androidx.ui.material.Shapes shapes;
     property public final androidx.ui.material.Typography typography;
-    field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+    field public static final androidx.ui.material.MaterialTheme INSTANCE;
   }
 
   public final class MaterialThemeKt {
@@ -163,7 +167,7 @@
   public final class ProgressIndicatorConstants {
     method public float getDefaultStrokeWidth();
     property public final float DefaultStrokeWidth;
-    field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+    field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
   }
 
   public final class ProgressIndicatorKt {
@@ -178,7 +182,7 @@
     method public long getDefaultUnselectedColor();
     property public final long defaultDisabledColor;
     property public final long defaultUnselectedColor;
-    field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+    field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
   }
 
   public final class RadioButtonKt {
@@ -193,10 +197,12 @@
   }
 
   public final class Scaffold {
-    field public static final androidx.ui.material.Scaffold! INSTANCE;
+    field public static final androidx.ui.material.Scaffold INSTANCE;
   }
 
   public enum Scaffold.FabPosition {
+    method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.material.Scaffold.FabPosition[] values();
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
     enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
   }
@@ -268,7 +274,7 @@
   public final class TabRow {
     method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
     method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
-    field public static final androidx.ui.material.TabRow! INSTANCE;
+    field public static final androidx.ui.material.TabRow INSTANCE;
   }
 
   @androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -284,7 +290,7 @@
   public final class TextButton {
     method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
     property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
-    field public static final androidx.ui.material.TextButton! INSTANCE;
+    field public static final androidx.ui.material.TextButton INSTANCE;
   }
 
   public final class TextFieldKt {
diff --git a/ui/ui-material/icons/core/api/0.1.0-dev15.txt b/ui/ui-material/icons/core/api/0.1.0-dev15.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/0.1.0-dev15.txt
+++ b/ui/ui-material/icons/core/api/0.1.0-dev15.txt
@@ -4,27 +4,27 @@
   public final class Icons {
     method public androidx.ui.material.icons.Icons.Filled getDefault();
     property public final androidx.ui.material.icons.Icons.Filled Default;
-    field public static final androidx.ui.material.icons.Icons! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons INSTANCE;
   }
 
   public static final class Icons.Filled {
-    field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
   }
 
   public static final class Icons.Outlined {
-    field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
   }
 
   public static final class Icons.Rounded {
-    field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
   }
 
   public static final class Icons.Sharp {
-    field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
   }
 
   public static final class Icons.TwoTone {
-    field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
   }
 
   public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/current.txt b/ui/ui-material/icons/core/api/current.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/current.txt
+++ b/ui/ui-material/icons/core/api/current.txt
@@ -4,27 +4,27 @@
   public final class Icons {
     method public androidx.ui.material.icons.Icons.Filled getDefault();
     property public final androidx.ui.material.icons.Icons.Filled Default;
-    field public static final androidx.ui.material.icons.Icons! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons INSTANCE;
   }
 
   public static final class Icons.Filled {
-    field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
   }
 
   public static final class Icons.Outlined {
-    field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
   }
 
   public static final class Icons.Rounded {
-    field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
   }
 
   public static final class Icons.Sharp {
-    field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
   }
 
   public static final class Icons.TwoTone {
-    field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
   }
 
   public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -4,27 +4,27 @@
   public final class Icons {
     method public androidx.ui.material.icons.Icons.Filled getDefault();
     property public final androidx.ui.material.icons.Icons.Filled Default;
-    field public static final androidx.ui.material.icons.Icons! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons INSTANCE;
   }
 
   public static final class Icons.Filled {
-    field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
   }
 
   public static final class Icons.Outlined {
-    field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
   }
 
   public static final class Icons.Rounded {
-    field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
   }
 
   public static final class Icons.Sharp {
-    field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
   }
 
   public static final class Icons.TwoTone {
-    field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
   }
 
   public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/public_plus_experimental_current.txt b/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
@@ -4,27 +4,27 @@
   public final class Icons {
     method public androidx.ui.material.icons.Icons.Filled getDefault();
     property public final androidx.ui.material.icons.Icons.Filled Default;
-    field public static final androidx.ui.material.icons.Icons! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons INSTANCE;
   }
 
   public static final class Icons.Filled {
-    field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
   }
 
   public static final class Icons.Outlined {
-    field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
   }
 
   public static final class Icons.Rounded {
-    field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
   }
 
   public static final class Icons.Sharp {
-    field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
   }
 
   public static final class Icons.TwoTone {
-    field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
   }
 
   public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt b/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt
@@ -4,27 +4,27 @@
   public final class Icons {
     method public androidx.ui.material.icons.Icons.Filled getDefault();
     property public final androidx.ui.material.icons.Icons.Filled Default;
-    field public static final androidx.ui.material.icons.Icons! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons INSTANCE;
   }
 
   public static final class Icons.Filled {
-    field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
   }
 
   public static final class Icons.Outlined {
-    field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
   }
 
   public static final class Icons.Rounded {
-    field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
   }
 
   public static final class Icons.Sharp {
-    field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
   }
 
   public static final class Icons.TwoTone {
-    field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
   }
 
   public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/restricted_current.txt b/ui/ui-material/icons/core/api/restricted_current.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/restricted_current.txt
+++ b/ui/ui-material/icons/core/api/restricted_current.txt
@@ -4,27 +4,27 @@
   public final class Icons {
     method public androidx.ui.material.icons.Icons.Filled getDefault();
     property public final androidx.ui.material.icons.Icons.Filled Default;
-    field public static final androidx.ui.material.icons.Icons! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons INSTANCE;
   }
 
   public static final class Icons.Filled {
-    field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
   }
 
   public static final class Icons.Outlined {
-    field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
   }
 
   public static final class Icons.Rounded {
-    field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
   }
 
   public static final class Icons.Sharp {
-    field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
   }
 
   public static final class Icons.TwoTone {
-    field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+    field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
   }
 
   public final class IconsKt {
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt
index 1fbd36c..ced42dc 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt
@@ -20,6 +20,7 @@
 import androidx.ui.core.Modifier
 import androidx.ui.foundation.Border
 import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
 import androidx.ui.foundation.shape.GenericShape
 import androidx.ui.graphics.Color
 import androidx.ui.layout.Arrangement
@@ -48,14 +49,16 @@
 
 @Composable
 fun ButtonDemo() {
-    Column(Modifier.padding(10.dp)) {
-        Buttons()
-        Spacer(Modifier.preferredHeight(DefaultSpace))
-        Fabs()
-        Spacer(Modifier.preferredHeight(DefaultSpace))
-        IconButtons()
-        Spacer(Modifier.preferredHeight(DefaultSpace))
-        CustomShapeButton()
+    VerticalScroller {
+        Column(Modifier.padding(10.dp)) {
+            Buttons()
+            Spacer(Modifier.preferredHeight(DefaultSpace))
+            Fabs()
+            Spacer(Modifier.preferredHeight(DefaultSpace))
+            IconButtons()
+            Spacer(Modifier.preferredHeight(DefaultSpace))
+            CustomShapeButton()
+        }
     }
 }
 
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt
index 01b89bb..d0bfe90 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt
@@ -18,6 +18,8 @@
 
 import androidx.compose.Composable
 import androidx.ui.foundation.VerticalScroller
+import androidx.ui.material.icons.Icons
+import androidx.ui.material.icons.filled.Call
 import androidx.ui.material.samples.OneLineListItems
 import androidx.ui.material.samples.ThreeLineListItems
 import androidx.ui.material.samples.TwoLineListItems
@@ -28,9 +30,10 @@
     val icon24 = imageResource(R.drawable.ic_bluetooth)
     val icon40 = imageResource(R.drawable.ic_account_box)
     val icon56 = imageResource(R.drawable.ic_android)
+    val vectorIcon = Icons.Default.Call
     VerticalScroller {
-        OneLineListItems(icon24, icon40, icon56)
+        OneLineListItems(icon24, icon40, icon56, vectorIcon)
         TwoLineListItems(icon24, icon40)
-        ThreeLineListItems(icon24, icon40)
+        ThreeLineListItems(icon24, vectorIcon)
     }
 }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt
index f7c1dbb..98fe32d 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt
@@ -30,9 +30,9 @@
     ComposableDemo("App Bars") { AppBarDemo() },
     ComposableDemo("Bottom Navigation") { BottomNavigationDemo() },
     ComposableDemo("Buttons & FABs") { ButtonDemo() },
-    DemoCategory("Drawer", listOf(
-        ComposableDemo("Modal") { ModalDrawerSample() },
-        ComposableDemo("Bottom") { BottomDrawerSample() }
+    DemoCategory("Navigation drawer", listOf(
+        ComposableDemo("Modal drawer") { ModalDrawerSample() },
+        ComposableDemo("Bottom drawer") { BottomDrawerSample() }
     )),
     ComposableDemo("Elevation") { ElevationDemo() },
     ComposableDemo("Emphasis") { EmphasisSample() },
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt
index cc4b52a..fea676e 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt
@@ -84,116 +84,122 @@
 
 @Composable
 fun MaterialTextFieldDemo() {
-    Column(Modifier.padding(10.dp)) {
-        var text by savedInstanceState { "" }
-        var leadingChecked by savedInstanceState { false }
-        var trailingChecked by savedInstanceState { false }
-        val characterCounterChecked by savedInstanceState { false }
-        var selectedOption by savedInstanceState { Option.None }
-        var selectedTextField by savedInstanceState { TextFieldType.Filled }
+    VerticalScroller {
+        Column(Modifier.padding(10.dp)) {
+            var text by savedInstanceState { "" }
+            var leadingChecked by savedInstanceState { false }
+            var trailingChecked by savedInstanceState { false }
+            val characterCounterChecked by savedInstanceState { false }
+            var selectedOption by savedInstanceState { Option.None }
+            var selectedTextField by savedInstanceState { TextFieldType.Filled }
 
-        val textField: @Composable () -> Unit = @Composable {
-            when (selectedTextField) {
-                TextFieldType.Filled ->
-                    FilledTextField(
-                        value = text,
-                        onValueChange = { text = it },
-                        label = {
-                            val label = "Label" + if (selectedOption == Option.Error) "*" else ""
-                            Text(text = label)
-                        },
-                        leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
-                        trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
-                        isErrorValue = selectedOption == Option.Error
-                    )
-                TextFieldType.Outlined ->
-                    OutlinedTextField(
-                        value = text,
-                        onValueChange = { text = it },
-                        label = {
-                            val label = "Label" + if (selectedOption == Option.Error) "*" else ""
-                            Text(text = label)
-                        },
-                        leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
-                        trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
-                        isErrorValue = selectedOption == Option.Error
-                    )
-            }
-        }
-
-        Box(Modifier.preferredHeight(150.dp).gravity(Alignment.CenterHorizontally)) {
-            if (selectedOption == Option.None) {
-                textField()
-            } else {
-                TextFieldWithMessage(textField, selectedOption)
-            }
-        }
-
-        Column {
-            Title("Text field type")
-            Column {
-                TextFieldType.values().map { it.name }.forEach { textType ->
-                    Row(Modifier
-                        .fillMaxWidth()
-                        .selectable(
-                            selected = (textType == selectedTextField.name),
-                            onClick = { selectedTextField = TextFieldType.valueOf(textType) }
+            val textField: @Composable () -> Unit = @Composable {
+                when (selectedTextField) {
+                    TextFieldType.Filled ->
+                        FilledTextField(
+                            value = text,
+                            onValueChange = { text = it },
+                            label = {
+                                val label =
+                                    "Label" + if (selectedOption == Option.Error) "*" else ""
+                                Text(text = label)
+                            },
+                            leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
+                            trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
+                            isErrorValue = selectedOption == Option.Error
                         )
-                        .padding(horizontal = 16.dp)
-                    ) {
-                        RadioButton(
-                            selected = (textType == selectedTextField.name),
-                            onClick = { selectedTextField = TextFieldType.valueOf(textType) }
+                    TextFieldType.Outlined ->
+                        OutlinedTextField(
+                            value = text,
+                            onValueChange = { text = it },
+                            label = {
+                                val label =
+                                    "Label" + if (selectedOption == Option.Error) "*" else ""
+                                Text(text = label)
+                            },
+                            leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
+                            trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
+                            isErrorValue = selectedOption == Option.Error
                         )
-                        Text(
-                            text = textType,
-                            style = MaterialTheme.typography.body1.merge(),
-                            modifier = Modifier.padding(start = 16.dp)
-                        )
-                    }
                 }
             }
 
-            Title("Options")
-            OptionRow(
-                title = "Leading icon",
-                checked = leadingChecked,
-                onCheckedChange = { leadingChecked = it }
-            )
-            OptionRow(
-                title = "Trailing icon",
-                checked = trailingChecked,
-                onCheckedChange = { trailingChecked = it }
-            )
-            OptionRow(
-                title = "Character counter (TODO)",
-                checked = characterCounterChecked,
-                enabled = false,
-                onCheckedChange = { /* TODO */ }
-            )
+            Box(Modifier.preferredHeight(150.dp).gravity(Alignment.CenterHorizontally)) {
+                if (selectedOption == Option.None) {
+                    textField()
+                } else {
+                    TextFieldWithMessage(textField, selectedOption)
+                }
+            }
 
-            Spacer(Modifier.preferredHeight(20.dp))
-
-            Title("Assistive text")
             Column {
-                Option.values().map { it.name }.forEach { text ->
-                    Row(Modifier
-                        .fillMaxWidth()
-                        .selectable(
-                            selected = (text == selectedOption.name),
-                            onClick = { selectedOption = Option.valueOf(text) }
-                        )
-                        .padding(horizontal = 16.dp)
-                    ) {
-                        RadioButton(
-                            selected = (text == selectedOption.name),
-                            onClick = { selectedOption = Option.valueOf(text) }
-                        )
-                        Text(
-                            text = text,
-                            style = MaterialTheme.typography.body1.merge(),
-                            modifier = Modifier.padding(start = 16.dp)
-                        )
+                Title("Text field type")
+                Column {
+                    TextFieldType.values().map { it.name }.forEach { textType ->
+                        Row(Modifier
+                            .fillMaxWidth()
+                            .selectable(
+                                selected = (textType == selectedTextField.name),
+                                onClick = {
+                                    selectedTextField = TextFieldType.valueOf(textType)
+                                }
+                            )
+                            .padding(horizontal = 16.dp)
+                        ) {
+                            RadioButton(
+                                selected = (textType == selectedTextField.name),
+                                onClick = { selectedTextField = TextFieldType.valueOf(textType) }
+                            )
+                            Text(
+                                text = textType,
+                                style = MaterialTheme.typography.body1.merge(),
+                                modifier = Modifier.padding(start = 16.dp)
+                            )
+                        }
+                    }
+                }
+
+                Title("Options")
+                OptionRow(
+                    title = "Leading icon",
+                    checked = leadingChecked,
+                    onCheckedChange = { leadingChecked = it }
+                )
+                OptionRow(
+                    title = "Trailing icon",
+                    checked = trailingChecked,
+                    onCheckedChange = { trailingChecked = it }
+                )
+                OptionRow(
+                    title = "Character counter (TODO)",
+                    checked = characterCounterChecked,
+                    enabled = false,
+                    onCheckedChange = { /* TODO */ }
+                )
+
+                Spacer(Modifier.preferredHeight(20.dp))
+
+                Title("Assistive text")
+                Column {
+                    Option.values().map { it.name }.forEach { text ->
+                        Row(Modifier
+                            .fillMaxWidth()
+                            .selectable(
+                                selected = (text == selectedOption.name),
+                                onClick = { selectedOption = Option.valueOf(text) }
+                            )
+                            .padding(horizontal = 16.dp)
+                        ) {
+                            RadioButton(
+                                selected = (text == selectedOption.name),
+                                onClick = { selectedOption = Option.valueOf(text) }
+                            )
+                            Text(
+                                text = text,
+                                style = MaterialTheme.typography.body1.merge(),
+                                modifier = Modifier.padding(start = 16.dp)
+                            )
+                        }
                     }
                 }
             }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt
index 6b3adf7..4331d1b 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt
@@ -28,9 +28,9 @@
 import androidx.compose.setValue
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
+import androidx.ui.foundation.VerticalScroller
 import androidx.ui.graphics.Color
 import androidx.ui.layout.Arrangement
-import androidx.ui.layout.Column
 import androidx.ui.layout.Row
 import androidx.ui.layout.fillMaxWidth
 import androidx.ui.material.CircularProgressIndicator
@@ -43,7 +43,7 @@
     onActive { state.start() }
     onDispose { state.stop() }
 
-    Column {
+    VerticalScroller {
         val modifier = Modifier.weight(1f, true)
             .gravity(Alignment.CenterHorizontally)
             .fillMaxWidth()
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt
index 820718f..485a171 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt
@@ -19,8 +19,11 @@
 import androidx.compose.Composable
 import androidx.ui.core.Modifier
 import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
 import androidx.ui.layout.Arrangement
 import androidx.ui.layout.Column
+import androidx.ui.layout.Spacer
+import androidx.ui.layout.height
 import androidx.ui.layout.padding
 import androidx.ui.material.MaterialTheme
 import androidx.ui.material.samples.RadioGroupSample
@@ -32,14 +35,19 @@
 @Composable
 fun SelectionControlsDemo() {
     val headerStyle = MaterialTheme.typography.h6
-    Column(Modifier.padding(10.dp), verticalArrangement = Arrangement.SpaceEvenly) {
-        Text(text = "Checkbox", style = headerStyle)
-        TriStateCheckboxSample()
-        Text(text = "Switch", style = headerStyle)
-        SwitchSample()
-        Text(text = "RadioButton", style = headerStyle)
-        RadioButtonSample()
-        Text(text = "Radio group", style = headerStyle)
-        RadioGroupSample()
+    VerticalScroller {
+        Column(Modifier.padding(10.dp), verticalArrangement = Arrangement.SpaceEvenly) {
+            Text(text = "Checkbox", style = headerStyle)
+            TriStateCheckboxSample()
+            Spacer(Modifier.height(16.dp))
+            Text(text = "Switch", style = headerStyle)
+            SwitchSample()
+            Spacer(Modifier.height(16.dp))
+            Text(text = "RadioButtons with custom colors", style = headerStyle)
+            RadioButtonSample()
+            Spacer(Modifier.height(16.dp))
+            Text(text = "Radio group", style = headerStyle)
+            RadioGroupSample()
+        }
     }
 }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt
index 93c46cd..9913748 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt
@@ -18,16 +18,26 @@
 
 import androidx.compose.Composable
 import androidx.ui.core.Modifier
+import androidx.ui.foundation.Text
 import androidx.ui.layout.Column
+import androidx.ui.layout.Spacer
+import androidx.ui.layout.height
 import androidx.ui.layout.padding
+import androidx.ui.material.MaterialTheme
 import androidx.ui.material.samples.SliderSample
 import androidx.ui.material.samples.StepsSliderSample
 import androidx.ui.unit.dp
 
 @Composable
 fun SliderDemo() {
+    val headerStyle = MaterialTheme.typography.h6
     Column(Modifier.padding(10.dp)) {
+        Text(text = "Continuous Slider", style = headerStyle)
+        Spacer(Modifier.height(16.dp))
         SliderSample()
+        Spacer(Modifier.height(16.dp))
+        Text(text = "Discrete Slider with custom color", style = headerStyle)
+        Spacer(Modifier.height(16.dp))
         StepsSliderSample()
     }
 }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt
index a605bce..26c8ba3 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt
@@ -19,6 +19,7 @@
 import androidx.compose.Composable
 import androidx.ui.core.Modifier
 import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
 import androidx.ui.layout.Column
 import androidx.ui.layout.padding
 import androidx.ui.material.MaterialTheme
@@ -30,22 +31,24 @@
 
 @Composable
 fun SnackbarDemo() {
-    Column(Modifier.padding(12.dp, 0.dp, 12.dp, 0.dp)) {
-        val textSpacing = Modifier.padding(top = 12.dp, bottom = 12.dp)
-        Text("Default Snackbar", modifier = textSpacing)
-        SimpleSnackbar()
-        Text("Snackbar with long text", modifier = textSpacing)
-        Snackbar(
-            text = { Text("This song already exists in the current playlist") },
-            action = {
-                TextButton(
-                    contentColor = snackbarPrimaryColorFor(MaterialTheme.colors),
-                    onClick = { /* perform undo */ }
-                ) {
-                    Text("ADD THIS SONG ANYWAY")
-                }
-            },
-            actionOnNewLine = true
-        )
+    VerticalScroller {
+        Column(Modifier.padding(12.dp, 0.dp, 12.dp, 0.dp)) {
+            val textSpacing = Modifier.padding(top = 12.dp, bottom = 12.dp)
+            Text("Default Snackbar", modifier = textSpacing)
+            SimpleSnackbar()
+            Text("Snackbar with long text", modifier = textSpacing)
+            Snackbar(
+                text = { Text("This song already exists in the current playlist") },
+                action = {
+                    TextButton(
+                        contentColor = snackbarPrimaryColorFor(MaterialTheme.colors),
+                        onClick = { /* perform undo */ }
+                    ) {
+                        Text("ADD THIS SONG ANYWAY")
+                    }
+                },
+                actionOnNewLine = true
+            )
+        }
     }
 }
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt
index 8321760..545d0f6 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt
@@ -21,11 +21,10 @@
 import androidx.ui.core.Alignment
 import androidx.ui.core.Modifier
 import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
 import androidx.ui.graphics.Color
-import androidx.ui.layout.Arrangement
-import androidx.ui.layout.Column
 import androidx.ui.layout.Spacer
-import androidx.ui.layout.fillMaxHeight
+import androidx.ui.layout.height
 import androidx.ui.layout.preferredHeight
 import androidx.ui.material.Button
 import androidx.ui.material.samples.FancyIndicatorContainerTabs
@@ -40,21 +39,29 @@
 
 @Composable
 fun TabDemo() {
-    Column(Modifier.fillMaxHeight(), verticalArrangement = Arrangement.SpaceBetween) {
+    VerticalScroller {
         val showingSimple = state { true }
         val buttonText = "Show ${if (showingSimple.value) "custom" else "simple"} tabs"
 
+        Spacer(Modifier.height(24.dp))
         if (showingSimple.value) {
             TextTabs()
+            Spacer(Modifier.height(24.dp))
             IconTabs()
+            Spacer(Modifier.height(24.dp))
             TextAndIconTabs()
+            Spacer(Modifier.height(24.dp))
             ScrollingTextTabs()
         } else {
             FancyTabs()
+            Spacer(Modifier.height(24.dp))
             FancyIndicatorTabs()
+            Spacer(Modifier.height(24.dp))
             FancyIndicatorContainerTabs()
+            Spacer(Modifier.height(24.dp))
             ScrollingFancyIndicatorContainerTabs()
         }
+        Spacer(Modifier.height(24.dp))
         Button(
             modifier = Modifier.gravity(Alignment.CenterHorizontally),
             onClick = {
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt
index 2766566..22f5e6c 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt
@@ -18,16 +18,27 @@
 
 import androidx.annotation.Sampled
 import androidx.compose.Composable
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.compose.state
+import androidx.ui.foundation.Icon
 import androidx.ui.foundation.Image
 import androidx.ui.foundation.Text
 import androidx.ui.graphics.ImageAsset
+import androidx.ui.graphics.vector.VectorAsset
 import androidx.ui.layout.Column
+import androidx.ui.material.Checkbox
 import androidx.ui.material.Divider
 import androidx.ui.material.ListItem
 
 @Sampled
 @Composable
-fun OneLineListItems(icon24x24: ImageAsset, icon40x40: ImageAsset, icon56x56: ImageAsset) {
+fun OneLineListItems(
+    icon24x24: ImageAsset,
+    icon40x40: ImageAsset,
+    icon56x56: ImageAsset,
+    vectorIcon: VectorAsset
+) {
     Column {
         ListItem(text = "One line list item with no icon")
         Divider()
@@ -43,13 +54,13 @@
         Divider()
         ListItem(
             text = { Text("One line list item with trailing icon") },
-            trailing = { Image(icon24x24) }
+            trailing = { Icon(vectorIcon) }
         )
         Divider()
         ListItem(
             text = { Text("One line list item") },
             icon = { Image(icon40x40) },
-            trailing = { Image(icon24x24) }
+            trailing = { Icon(vectorIcon) }
         )
         Divider()
     }
@@ -57,6 +68,7 @@
 
 @Sampled
 @Composable
+// TODO(popam, b/159689286): material icons instead of ImageAsset when they can have custom sizes
 fun TwoLineListItems(icon24x24: ImageAsset, icon40x40: ImageAsset) {
     Column {
         ListItem(text = "Two line list item", secondaryText = "Secondary text")
@@ -82,13 +94,13 @@
             icon = icon40x40
         )
         Divider()
+        var checked by state { false }
         ListItem(
             text = { Text("Two line list item") },
             secondaryText = { Text("Secondary text") },
             icon = { Image(icon40x40) },
             trailing = {
-                // TODO(popam): put checkbox here after b/140292836 is fixed
-                Image(icon24x24)
+                Checkbox(checked, onCheckedChange = { checked = !checked })
             }
         )
         Divider()
@@ -97,7 +109,7 @@
 
 @Sampled
 @Composable
-fun ThreeLineListItems(icon24x24: ImageAsset, icon40x40: ImageAsset) {
+fun ThreeLineListItems(icon24x24: ImageAsset, vectorIcon: VectorAsset) {
     Column {
         ListItem(
             text = "Three line list item",
@@ -126,7 +138,7 @@
             secondaryText = { Text("This is a long secondary text for the current list" +
                 " item, displayed on two lines") },
             singleLineSecondaryText = false,
-            trailing = { Image(icon40x40) }
+            trailing = { Icon(vectorIcon) }
         )
         Divider()
         ListItem(
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt
index 2ced5f6..bea103f 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt
@@ -61,7 +61,11 @@
             onStateChange2(s)
         }
 
-        TriStateCheckbox(state = parentState, onClick = onParentClick, checkedColor = Color.Black)
+        TriStateCheckbox(
+            state = parentState,
+            onClick = onParentClick,
+            checkedColor = MaterialTheme.colors.primary
+        )
         Column(Modifier.padding(10.dp, 0.dp, 0.dp, 0.dp)) {
             Checkbox(state, onStateChange)
             Checkbox(state2, onStateChange2)
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt
index b1d57c4..8922b3c 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt
@@ -21,7 +21,7 @@
 import androidx.compose.getValue
 import androidx.compose.setValue
 import androidx.compose.state
-import androidx.ui.graphics.Color
+import androidx.ui.material.MaterialTheme
 import androidx.ui.material.Slider
 
 @Sampled
@@ -40,6 +40,6 @@
         onValueChange = { sliderPosition = it },
         valueRange = 0f..100f,
         steps = 5,
-        color = Color.Black
+        color = MaterialTheme.colors.secondary
     )
 }
\ No newline at end of file
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 beedf75..e6d6c1e 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
@@ -18,7 +18,6 @@
 
 import androidx.compose.Composable
 import androidx.test.filters.SmallTest
-import androidx.ui.text.LastBaseline
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.Modifier
 import androidx.ui.core.globalPosition
@@ -36,7 +35,6 @@
 import androidx.ui.text.TextStyle
 import androidx.ui.unit.Density
 import androidx.ui.unit.dp
-import androidx.ui.unit.sp
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -78,8 +76,6 @@
         var appBarCoords: LayoutCoordinates? = null
         var navigationIconCoords: LayoutCoordinates? = null
         var titleCoords: LayoutCoordinates? = null
-        // Position of the baseline relative to the top of the text
-        var titleLastBaselineRelativePosition: Float? = null
         var actionCoords: LayoutCoordinates? = null
         composeTestRule.setMaterialContent {
             Box(Modifier.onChildPositioned { appBarCoords = it }) {
@@ -88,10 +84,7 @@
                         FakeIcon(Modifier.onPositioned { navigationIconCoords = it })
                     },
                     title = {
-                        Text("title", Modifier.onPositioned { coords: LayoutCoordinates ->
-                            titleCoords = coords
-                            titleLastBaselineRelativePosition = coords[LastBaseline].toFloat()
-                        })
+                        Text("title", Modifier.onPositioned { titleCoords = it })
                     },
                     actions = {
                         FakeIcon(Modifier.onPositioned { actionCoords = it })
@@ -122,13 +115,12 @@
             val titleExpectedPositionX = (4.dp.toIntPx() + 68.dp.toIntPx()).toFloat()
             assertThat(titlePositionX).isEqualTo(titleExpectedPositionX)
 
-            // Absolute position of the baseline
-            val titleLastBaselinePositionY = titleLastBaselineRelativePosition!! +
-                    titleCoords!!.globalPosition.y
-            // Baseline should be 20.sp from the bottom of the app bar
-            val titleExpectedLastBaselinePositionY =
-                (appBarBottomEdgeY - 20.sp.toIntPx().toFloat())
-            assertThat(titleLastBaselinePositionY).isEqualTo(titleExpectedLastBaselinePositionY)
+            // Title should be vertically centered
+            val titlePositionY = titleCoords!!.globalPosition.y
+            val titleHeight = titleCoords!!.size.height
+            val appBarHeight = appBarCoords!!.size.height
+            val titleExpectedPositionY = (appBarHeight - titleHeight) / 2
+            assertThat(titlePositionY).isEqualTo(titleExpectedPositionY)
 
             // Action should be placed at the end
             val actionPositionX = actionCoords!!.globalPosition.x
@@ -154,8 +146,7 @@
             Box(Modifier.onChildPositioned { appBarCoords = it }) {
                 TopAppBar(
                     title = {
-                        Text("title",
-                            Modifier.onPositioned { titleCoords = it })
+                        Text("title", Modifier.onPositioned { titleCoords = it })
                     },
                     actions = {
                         FakeIcon(Modifier.onPositioned { actionCoords = it })
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 9f2424b..8b5e326 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
@@ -29,11 +29,14 @@
 import androidx.ui.foundation.selection.ToggleableState
 import androidx.ui.layout.wrapContentSize
 import androidx.ui.test.captureToBitmap
+import androidx.ui.test.center
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doClick
+import androidx.ui.test.doPartialGesture
 import androidx.ui.test.find
 import androidx.ui.test.findByTag
 import androidx.ui.test.isToggleable
+import androidx.ui.test.sendDown
 import androidx.ui.test.waitForIdle
 import org.junit.Rule
 import org.junit.Test
@@ -78,6 +81,19 @@
     }
 
     @Test
+    fun checkBoxTest_pressed() {
+        composeTestRule.setMaterialContent {
+            Box(wrap.semantics().testTag(wrapperTestTag)) {
+                Checkbox(modifier = wrap, checked = false, onCheckedChange = { })
+            }
+        }
+        findByTag(wrapperTestTag).doPartialGesture {
+            sendDown(center)
+        }
+        assertToggeableAgainstGolden("checkbox_pressed")
+    }
+
+    @Test
     fun checkBoxTest_indeterminate() {
         composeTestRule.setMaterialContent {
             Box(wrap.semantics().testTag(wrapperTestTag)) {
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
index a5512a9..ed16c4a 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
@@ -46,7 +46,10 @@
 import androidx.ui.unit.IntOffset
 import androidx.ui.unit.IntSize
 import androidx.ui.unit.Position
+import androidx.ui.unit.PxBounds
 import androidx.ui.unit.dp
+import androidx.ui.unit.toOffset
+import androidx.ui.unit.toSize
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -234,6 +237,51 @@
     }
 
     @Test
+    fun menu_positioning_callback() {
+        val screenWidth = 500
+        val screenHeight = 1000
+        val density = Density(1f)
+        val displayMetrics = DisplayMetrics().apply {
+            widthPixels = screenWidth
+            heightPixels = screenHeight
+        }
+        val anchorPosition = IntOffset(100, 200)
+        val anchorSize = IntSize(10, 20)
+        val inset = with(density) { MenuElevation.toIntPx() }
+        val offsetX = 20
+        val offsetY = 40
+        val popupSize = IntSize(50, 80)
+
+        var obtainedParentBounds = PxBounds(0f, 0f, 0f, 0f)
+        var obtainedMenuBounds = PxBounds(0f, 0f, 0f, 0f)
+        DropdownMenuPositionProvider(
+            Position(offsetX.dp, offsetY.dp),
+            density,
+            displayMetrics
+        ) { parentBounds, menuBounds ->
+            obtainedParentBounds = parentBounds
+            obtainedMenuBounds = menuBounds
+        }.calculatePosition(
+            anchorPosition,
+            anchorSize,
+            LayoutDirection.Ltr,
+            popupSize
+        )
+
+        assertThat(obtainedParentBounds).isEqualTo(
+            PxBounds(anchorPosition.toOffset(), anchorSize.toSize())
+        )
+        assertThat(obtainedMenuBounds).isEqualTo(
+            PxBounds(
+                anchorPosition.x.toFloat() + anchorSize.width - inset + offsetX,
+                anchorPosition.y.toFloat() + anchorSize.height - inset + offsetY,
+                anchorPosition.x.toFloat() + anchorSize.width - inset + offsetX + popupSize.width,
+                anchorPosition.y.toFloat() + anchorSize.height - inset + offsetY + popupSize.height
+            )
+        )
+    }
+
+    @Test
     fun dropdownMenuItem_emphasis() {
         var onSurface = Color.Unset
         var enabledContentColor = Color.Unset
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
index 23f5c3d..abe539d 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
@@ -29,11 +29,14 @@
 import androidx.ui.foundation.Box
 import androidx.ui.layout.wrapContentSize
 import androidx.ui.test.captureToBitmap
+import androidx.ui.test.center
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doClick
+import androidx.ui.test.doPartialGesture
 import androidx.ui.test.find
 import androidx.ui.test.findByTag
 import androidx.ui.test.isInMutuallyExclusiveGroup
+import androidx.ui.test.sendDown
 import androidx.ui.test.waitForIdle
 import org.junit.Rule
 import org.junit.Test
@@ -78,6 +81,19 @@
     }
 
     @Test
+    fun radioButtonTest_pressed() {
+        composeTestRule.setMaterialContent {
+            Box(wrap.semantics().testTag(wrapperTestTag)) {
+                RadioButton(selected = false, onClick = {})
+            }
+        }
+        findByTag(wrapperTestTag).doPartialGesture {
+            sendDown(center)
+        }
+        assertSelectableAgainstGolden("radioButton_pressed")
+    }
+
+    @Test
     fun radioButtonTest_disabled_selected() {
         composeTestRule.setMaterialContent {
             Box(wrap.semantics().testTag(wrapperTestTag)) {
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
index bcf3822..58317f67 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
@@ -16,21 +16,34 @@
 
 package androidx.ui.material
 
+import android.os.Build
 import androidx.compose.mutableStateOf
 import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
 import androidx.ui.core.testTag
+import androidx.ui.foundation.drawBackground
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.compositeOver
+import androidx.ui.graphics.toArgb
 import androidx.ui.layout.DpConstraints
 import androidx.ui.test.assertValueEquals
+import androidx.ui.test.captureToBitmap
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.findByTag
 import androidx.ui.test.runOnIdleCompose
 import androidx.ui.test.runOnUiThread
 import androidx.ui.unit.dp
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import kotlin.math.ceil
+import kotlin.math.floor
+import kotlin.math.sqrt
 
 @MediumTest
 @RunWith(JUnit4::class)
@@ -99,4 +112,80 @@
             .assertHeightEqualsTo(48.dp)
             .assertWidthEqualsTo(100.dp)
     }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun slider_endsAreRounded() {
+        val sliderTag = "slider"
+        var thumbStrokeWidth = 0
+        var thumbPx = 0
+        composeTestRule.setMaterialContent {
+            with(DensityAmbient.current) {
+                thumbStrokeWidth = TrackHeight.toIntPx()
+                thumbPx = ThumbRadius.toIntPx()
+            }
+            Slider(modifier = Modifier.testTag(sliderTag).drawBackground(Color.Gray),
+                color = Color.Green,
+                value = 0.5f,
+                onValueChange = {}
+            )
+        }
+
+        findByTag(sliderTag).captureToBitmap().apply {
+            assertNotEquals(0, thumbStrokeWidth)
+            assertNotEquals(0, thumbPx)
+
+            val compositedColor =
+                Color.Green.copy(alpha = InactiveTrackColorAlpha).compositeOver(Color.Gray)
+
+            val hyp = sqrt(2.0) / 2
+            val radius = thumbStrokeWidth / 2
+
+            val left = floor(thumbPx - radius * hyp).toInt()
+            val upper = floor(height / 2 - radius * hyp).toInt()
+            // top left outside the rounded area has the background color
+            assertEquals(getPixel(left - 1, upper - 1), Color.Gray.toArgb())
+            // top left inside the rounded area by a few pixels has the track color
+            assertEquals(getPixel(left + 3, upper + 3), Color.Green.toArgb())
+
+            val lower = ceil(height / 2 + radius * hyp).toInt()
+            // bottom left outside the rounded area has the background color
+            assertEquals(getPixel(left - 1, lower + 1), Color.Gray.toArgb())
+            // bottom left inside the rounded area by a few pixels has the track color
+            assertEquals(getPixel(left + 3, lower - 3), Color.Green.toArgb())
+
+            // top right outside the rounded area has the background color
+            val right = ceil(width - thumbPx + radius * hyp).toInt()
+            assertEquals(getPixel(right + 1, upper - 1), Color.Gray.toArgb())
+
+            // top right inside the rounded area has the track color with the
+            // inactive opacity composited over the background
+            val upperRightInsideColor = Color(getPixel(right - 3, upper + 3))
+            assertEquals(upperRightInsideColor.alpha, compositedColor.alpha, 0.01f)
+            assertEquals(upperRightInsideColor.red, compositedColor.red, 0.01f)
+            assertEquals(upperRightInsideColor.blue, compositedColor.blue, 0.01f)
+            assertEquals(upperRightInsideColor.green, compositedColor.green, 0.01f)
+
+            // lower right outside the rounded area has the background color
+            assertEquals(getPixel(right + 1, lower + 1), Color.Gray.toArgb())
+
+            // lower right inside the rounded area has the track color with the
+            // inactive opacity composited over the background
+            val lowerRightInsideColor = Color(getPixel(right - 3, lower - 3))
+            assertEquals(lowerRightInsideColor.alpha, compositedColor.alpha, 0.01f)
+            assertEquals(lowerRightInsideColor.red, compositedColor.red, 0.01f)
+            assertEquals(lowerRightInsideColor.blue, compositedColor.blue, 0.01f)
+            assertEquals(lowerRightInsideColor.green, compositedColor.green, 0.01f)
+
+            // left along the center has the track color
+            assertEquals(getPixel(thumbPx, height / 2), Color.Green.toArgb())
+
+            // right along the center has the modulated color composited over the background
+            val actualColor = Color(getPixel(width - thumbPx, height / 2))
+            assertEquals(actualColor.alpha, compositedColor.alpha, 0.01f)
+            assertEquals(actualColor.red, compositedColor.red, 0.01f)
+            assertEquals(actualColor.blue, compositedColor.blue, 0.01f)
+            assertEquals(actualColor.green, compositedColor.green, 0.01f)
+        }
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchScreenshotTest.kt
new file mode 100644
index 0000000..6f2b19d
--- /dev/null
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchScreenshotTest.kt
@@ -0,0 +1,183 @@
+/*
+ * 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
+
+import android.os.Build
+import androidx.compose.state
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import androidx.test.screenshot.assertAgainstGolden
+import androidx.ui.core.Alignment
+import androidx.ui.core.Modifier
+import androidx.ui.core.testTag
+import androidx.ui.foundation.Box
+import androidx.ui.graphics.Color
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.test.captureToBitmap
+import androidx.ui.test.center
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.doClick
+import androidx.ui.test.doPartialGesture
+import androidx.ui.test.find
+import androidx.ui.test.findByTag
+import androidx.ui.test.isToggleable
+import androidx.ui.test.sendDown
+import androidx.ui.test.waitForIdle
+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 SwitchScreenshotTest {
+
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL)
+
+    // TODO: this test tag as well as Boxes inside testa are temporarty, remove then b/157687898
+    //  is fixed
+    private val wrapperTestTag = "switchWrapper"
+
+    private val wrapperModifier = Modifier
+        .wrapContentSize(Alignment.TopStart)
+        .testTag(wrapperTestTag)
+
+    @Test
+    fun switchTest_checked() {
+        composeTestRule.setMaterialContent {
+            Box(wrapperModifier) {
+                Switch(checked = true, onCheckedChange = { })
+            }
+        }
+        assertToggeableAgainstGolden("switch_checked")
+    }
+
+    @Test
+    fun switchTest_checked_customColor() {
+        composeTestRule.setMaterialContent {
+            Box(wrapperModifier) {
+                Switch(checked = true, onCheckedChange = { }, color = Color.Red)
+            }
+        }
+        assertToggeableAgainstGolden("switch_checked_customColor")
+    }
+
+    @Test
+    fun switchTest_unchecked() {
+        composeTestRule.setMaterialContent {
+            Box(wrapperModifier) {
+                Switch(checked = false, onCheckedChange = { })
+            }
+        }
+        assertToggeableAgainstGolden("switch_unchecked")
+    }
+
+    @Test
+    fun switchTest_pressed() {
+        composeTestRule.setMaterialContent {
+            Box(wrapperModifier) {
+                Switch(checked = false, enabled = true, onCheckedChange = { })
+            }
+        }
+
+        findByTag(wrapperTestTag).doPartialGesture {
+            sendDown(center)
+        }
+        assertToggeableAgainstGolden("switch_pressed")
+    }
+
+    @Test
+    fun switchTest_disabled_checked() {
+        composeTestRule.setMaterialContent {
+            Box(wrapperModifier) {
+                Switch(checked = true, enabled = false, onCheckedChange = { })
+            }
+        }
+        assertToggeableAgainstGolden("switch_disabled_checked")
+    }
+
+    @Test
+    fun switchTest_disabled_unchecked() {
+        composeTestRule.setMaterialContent {
+            Box(wrapperModifier) {
+                Switch(checked = false, enabled = false, onCheckedChange = { })
+            }
+        }
+        assertToggeableAgainstGolden("switch_disabled_unchecked")
+    }
+
+    @Test
+    fun switchTest_unchecked_animateToChecked() {
+        composeTestRule.setMaterialContent {
+            val isChecked = state { false }
+            Box(wrapperModifier) {
+                Switch(
+                    checked = isChecked.value,
+                    onCheckedChange = { isChecked.value = it }
+                )
+            }
+        }
+
+        composeTestRule.clockTestRule.pauseClock()
+
+        find(isToggleable())
+            .doClick()
+
+        waitForIdle()
+
+        composeTestRule.clockTestRule.advanceClock(60)
+
+        assertToggeableAgainstGolden("switch_animateToChecked")
+    }
+
+    @Test
+    fun switchTest_checked_animateToUnchecked() {
+        composeTestRule.setMaterialContent {
+            val isChecked = state { true }
+            Box(wrapperModifier) {
+                Switch(
+                    checked = isChecked.value,
+                    onCheckedChange = { isChecked.value = it }
+                )
+            }
+        }
+
+        composeTestRule.clockTestRule.pauseClock()
+
+        find(isToggleable())
+            .doClick()
+
+        waitForIdle()
+
+        composeTestRule.clockTestRule.advanceClock(60)
+
+        assertToggeableAgainstGolden("switch_animateToUnchecked")
+    }
+
+    private fun assertToggeableAgainstGolden(goldenName: String) {
+        // TODO: replace with find(isToggeable()) after b/157687898 is fixed
+        findByTag(wrapperTestTag)
+            .captureToBitmap()
+            .assertAgainstGolden(screenshotRule, goldenName)
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchUiTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchTest.kt
similarity index 99%
rename from ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchUiTest.kt
rename to ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchTest.kt
index 20ac970..9767264 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchUiTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchTest.kt
@@ -39,7 +39,7 @@
 
 @MediumTest
 @RunWith(JUnit4::class)
-class SwitchUiTest {
+class SwitchTest {
 
     @get:Rule
     val composeTestRule = createComposeRule(disableTransitions = true)
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 d59924b..24f5c3f 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
@@ -20,11 +20,8 @@
 import androidx.compose.setValue
 import androidx.compose.state
 import androidx.test.filters.LargeTest
-import androidx.ui.text.LastBaseline
-import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.Modifier
-import androidx.ui.core.onChildPositioned
-import androidx.ui.core.onPositioned
+import androidx.ui.core.testTag
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.Icon
 import androidx.ui.foundation.Text
@@ -32,7 +29,6 @@
 import androidx.ui.graphics.Color
 import androidx.ui.layout.fillMaxWidth
 import androidx.ui.layout.preferredHeight
-import androidx.ui.layout.preferredWidth
 import androidx.ui.material.icons.Icons
 import androidx.ui.material.icons.filled.Favorite
 import androidx.ui.material.samples.ScrollingTextTabs
@@ -40,13 +36,18 @@
 import androidx.ui.test.assertCountEquals
 import androidx.ui.test.assertIsSelected
 import androidx.ui.test.assertIsUnselected
+import androidx.ui.test.assertPositionInRootIsEqualTo
 import androidx.ui.test.createComposeRule
 import androidx.ui.test.doClick
 import androidx.ui.test.findAll
+import androidx.ui.test.findByTag
+import androidx.ui.test.getAlignmentLinePosition
+import androidx.ui.test.getBoundsInRoot
 import androidx.ui.test.isInMutuallyExclusiveGroup
-import androidx.ui.test.runOnIdleCompose
-import androidx.ui.geometry.Offset
+import androidx.ui.text.LastBaseline
 import androidx.ui.unit.dp
+import androidx.ui.unit.height
+import androidx.ui.unit.width
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -108,8 +109,6 @@
     @Test
     fun fixedTabRow_indicatorPosition() {
         val indicatorHeight = 1.dp
-        lateinit var tabRowCoords: LayoutCoordinates
-        lateinit var indicatorCoords: LayoutCoordinates
 
         composeTestRule.setMaterialContent {
             var state by state { 0 }
@@ -118,15 +117,15 @@
             val indicatorContainer = @Composable { tabPositions: List<TabRow.TabPosition> ->
                 TabRow.IndicatorContainer(tabPositions, state) {
                     Box(Modifier
-                        .onPositioned { indicatorCoords = it }
                         .fillMaxWidth()
                         .preferredHeight(indicatorHeight)
                         .drawBackground(Color.Red)
+                        .testTag("indicator")
                     )
                 }
             }
 
-            Box(Modifier.onChildPositioned { tabRowCoords = it }) {
+            Box(Modifier.testTag("tabRow")) {
                 TabRow(
                     items = titles,
                     selectedIndex = state,
@@ -141,62 +140,41 @@
             }
         }
 
-        val (tabRowWidth, tabRowHeight) = composeTestRule.runOnIdleComposeWithDensity {
-            val tabRowWidth = tabRowCoords.size.width
-            val tabRowHeight = tabRowCoords.size.height
+        val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
 
-            val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
-            val expectedPositionX = 0.dp.toPx()
-            assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
-            val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
-            val expectedPositionY = (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
-            assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
-
-            tabRowWidth to tabRowHeight
-        }
+        findByTag("indicator")
+            .assertPositionInRootIsEqualTo(
+                expectedLeft = 0.dp,
+                expectedTop = tabRowBounds.height - indicatorHeight
+            )
 
         // Click the second tab
         findAll(isInMutuallyExclusiveGroup())[1].doClick()
 
         // 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
-        runOnIdleCompose {
-            with(composeTestRule.density) {
-                val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
-                val expectedPositionX = (tabRowWidth / 2).toFloat()
-                assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
-                val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
-                val expectedPositionY =
-                    (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
-                assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
-            }
-        }
+        findByTag("indicator")
+            .assertPositionInRootIsEqualTo(
+                expectedLeft = (tabRowBounds.width / 2),
+                expectedTop = tabRowBounds.height - indicatorHeight
+            )
     }
 
     @Test
     fun singleLineTab_textBaseline() {
-        lateinit var tabRowCoords: LayoutCoordinates
-        lateinit var textCoords: LayoutCoordinates
-        var textBaseline = Float.NEGATIVE_INFINITY
-
         composeTestRule.setMaterialContent {
             var state by state { 0 }
             val titles = listOf("TAB")
 
             Box {
                 TabRow(
-                    modifier = Modifier.onPositioned { tabRowCoords = it },
+                    modifier = Modifier.testTag("tabRow"),
                     items = titles,
                     selectedIndex = state
                 ) { index, text ->
                     Tab(
                         text = {
-                            Text(text, Modifier.onPositioned { coords: LayoutCoordinates ->
-                                textCoords = coords
-                                textBaseline = coords[LastBaseline].toFloat()
-                            })
+                            Text(text, Modifier.testTag("text"))
                         },
                         selected = state == index,
                         onSelected = { state = index }
@@ -205,43 +183,35 @@
             }
         }
 
-        composeTestRule.runOnIdleComposeWithDensity {
-            val expectedBaseline = 18.dp
-            val indicatorHeight = 2.dp
-            val expectedBaselineDistance =
-                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toFloat()
+        val expectedBaseline = 18.dp
+        val indicatorHeight = 2.dp
+        val expectedBaselineDistance = expectedBaseline + indicatorHeight
 
-            val tabRowHeight = tabRowCoords.size.height
+        val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
+        val textBounds = findByTag("text").getBoundsInRoot()
+        val textBaselinePos = findByTag("text").getAlignmentLinePosition(LastBaseline)
 
-            val textPositionY = textCoords.localToGlobal(Offset.Zero).y
-            val baselinePositionY = textPositionY + textBaseline
-            val expectedPositionY = (tabRowHeight.toFloat() - expectedBaselineDistance)
-            assertThat(baselinePositionY).isEqualTo(expectedPositionY)
-        }
+        val baselinePositionY = textBounds.top + textBaselinePos
+        val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
+
+        assertThat(baselinePositionY.value).isWithin(0.5f).of(expectedPositionY.value)
     }
 
     @Test
     fun singleLineTab_withIcon_textBaseline() {
-        lateinit var tabRowCoords: LayoutCoordinates
-        lateinit var textCoords: LayoutCoordinates
-        var textBaseline = Float.NEGATIVE_INFINITY
-
         composeTestRule.setMaterialContent {
             var state by state { 0 }
             val titles = listOf("TAB")
 
             Box {
                 TabRow(
-                    modifier = Modifier.onPositioned { tabRowCoords = it },
+                    modifier = Modifier.testTag("tabRow"),
                     items = titles,
                     selectedIndex = state
                 ) { index, text ->
                     Tab(
                         text = {
-                            Text(text, Modifier.onPositioned { coords: LayoutCoordinates ->
-                                textCoords = coords
-                                textBaseline = coords[LastBaseline].toFloat()
-                            })
+                            Text(text, Modifier.testTag("text"))
                         },
                         icon = { Icon(Icons.Filled.Favorite) },
                         selected = state == index,
@@ -251,43 +221,34 @@
             }
         }
 
-        composeTestRule.runOnIdleComposeWithDensity {
-            val expectedBaseline = 14.dp
-            val indicatorHeight = 2.dp
-            val expectedBaselineDistance =
-                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toFloat()
+        val expectedBaseline = 14.dp
+        val indicatorHeight = 2.dp
+        val expectedBaselineDistance = expectedBaseline + indicatorHeight
 
-            val tabRowHeight = tabRowCoords.size.height
+        val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
+        val textBounds = findByTag("text").getBoundsInRoot()
+        val textBaselinePos = findByTag("text").getAlignmentLinePosition(LastBaseline)
 
-            val textPositionY = textCoords.localToGlobal(Offset.Zero).y
-            val baselinePositionY = textPositionY + textBaseline
-            val expectedPositionY = (tabRowHeight.toFloat() - expectedBaselineDistance)
-            assertThat(baselinePositionY).isEqualTo(expectedPositionY)
-        }
+        val baselinePositionY = textBounds.top + textBaselinePos
+        val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
+        assertThat(baselinePositionY).isEqualTo(expectedPositionY)
     }
 
     @Test
     fun twoLineTab_textBaseline() {
-        lateinit var tabRowCoords: LayoutCoordinates
-        lateinit var textCoords: LayoutCoordinates
-        var textBaseline = Float.NEGATIVE_INFINITY
-
         composeTestRule.setMaterialContent {
             var state by state { 0 }
             val titles = listOf("VERY LONG TAB TITLE THAT WILL BE FORCED TO GO TO TWO LINES")
 
             Box {
                 TabRow(
-                    modifier = Modifier.onPositioned { tabRowCoords = it },
+                    modifier = Modifier.testTag("tabRow"),
                     items = titles,
                     selectedIndex = state
                 ) { index, text ->
                     Tab(
                         text = {
-                            Text(text, Modifier.preferredWidth(100.dp).onPositioned { coords ->
-                                textCoords = coords
-                                textBaseline = coords[LastBaseline].toFloat()
-                            }, maxLines = 2)
+                            Text(text, Modifier.testTag("text"), maxLines = 2)
                         },
                         selected = state == index,
                         onSelected = { state = index }
@@ -296,19 +257,18 @@
             }
         }
 
-        composeTestRule.runOnIdleComposeWithDensity {
-            val expectedBaseline = 10.dp
-            val indicatorHeight = 2.dp
-            val expectedBaselineDistance =
-                (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toFloat()
+        val expectedBaseline = 10.dp
+        val indicatorHeight = 2.dp
 
-            val tabRowHeight = tabRowCoords.size.height
+        val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
+        val textBounds = findByTag("text").getBoundsInRoot()
+        val textBaselinePos = findByTag("text").getAlignmentLinePosition(LastBaseline)
 
-            val textPositionY = textCoords.localToGlobal(Offset.Zero).y
-            val baselinePositionY = textPositionY + textBaseline
-            val expectedPositionY = (tabRowHeight.toFloat() - expectedBaselineDistance)
-            assertThat(baselinePositionY).isEqualTo(expectedPositionY)
-        }
+        val expectedBaselineDistance = expectedBaseline + indicatorHeight
+
+        val baselinePositionY = textBounds.top + textBaselinePos
+        val expectedPositionY = (tabRowBounds.height - expectedBaselineDistance)
+        assertThat(baselinePositionY.value).isWithin(0.5f).of(expectedPositionY.value)
     }
 
     @Test
@@ -316,8 +276,6 @@
         val indicatorHeight = 1.dp
         val scrollableTabRowOffset = 52.dp
         val minimumTabWidth = 90.dp
-        lateinit var tabRowCoords: LayoutCoordinates
-        lateinit var indicatorCoords: LayoutCoordinates
 
         composeTestRule.setMaterialContent {
             var state by state { 0 }
@@ -326,17 +284,17 @@
             val indicatorContainer = @Composable { tabPositions: List<TabRow.TabPosition> ->
                 TabRow.IndicatorContainer(tabPositions, state) {
                     Box(Modifier
-                        .onPositioned { indicatorCoords = it }
                         .fillMaxWidth()
                         .preferredHeight(indicatorHeight)
                         .drawBackground(Color.Red)
+                        .testTag("indicator")
                     )
                 }
             }
 
             Box {
                 TabRow(
-                    modifier = Modifier.onPositioned { tabRowCoords = it },
+                    modifier = Modifier.testTag("tabRow"),
                     items = titles,
                     scrollable = true,
                     selectedIndex = state,
@@ -351,38 +309,26 @@
             }
         }
 
-        val tabRowHeight = composeTestRule.runOnIdleComposeWithDensity {
-            val tabRowHeight = tabRowCoords.size.height
+        val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
 
-            // Indicator should be placed in the bottom left of the first tab
-            val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
-            // Tabs in a scrollable tab row are offset 52.dp from each end
-            val expectedPositionX = scrollableTabRowOffset.toIntPx().toFloat()
-            assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
-            val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
-            val expectedPositionY = (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
-            assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
-
-            tabRowHeight
-        }
+        // Indicator should be placed in the bottom left of the first tab
+        findByTag("indicator")
+            .assertPositionInRootIsEqualTo(
+                // Tabs in a scrollable tab row are offset 52.dp from each end
+                expectedLeft = scrollableTabRowOffset,
+                expectedTop = tabRowBounds.height - indicatorHeight
+            )
 
         // Click the second tab
         findAll(isInMutuallyExclusiveGroup())[1].doClick()
 
         // 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(Offset.Zero).x
-            val expectedPositionX =
-                (scrollableTabRowOffset + minimumTabWidth).toIntPx().toFloat()
-            assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
-            val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
-            val expectedPositionY =
-                (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
-            assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
-        }
+        findByTag("indicator")
+            .assertPositionInRootIsEqualTo(
+                expectedLeft = scrollableTabRowOffset + minimumTabWidth,
+                expectedTop = tabRowBounds.height - indicatorHeight
+            )
     }
 
     @Test
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
new file mode 100644
index 0000000..38893bc
--- /dev/null
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
@@ -0,0 +1,193 @@
+/*
+ * 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.textfield
+
+import android.os.Build
+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.Text
+import androidx.ui.layout.rtl
+import androidx.ui.material.FilledTextField
+import androidx.ui.material.GOLDEN_MATERIAL
+import androidx.ui.material.OutlinedTextField
+import androidx.ui.material.setMaterialContent
+import androidx.ui.test.captureToBitmap
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.doClick
+import androidx.ui.test.findByTag
+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 TextFieldScreenshotTest {
+
+    private val TextFieldTag = "textField"
+
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL)
+
+    @Test
+    fun outlinedTextField_withInput() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+                OutlinedTextField(
+                    value = "Text",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        assertAgainstGolden("outlined_textField_withInput")
+    }
+
+    @Test
+    fun outlinedTextField_notFocused() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+                OutlinedTextField(
+                    value = "",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        assertAgainstGolden("outlined_textField_not_focused")
+    }
+
+    @Test
+    fun outlinedTextField_focused() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+                OutlinedTextField(
+                    value = "",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        findByTag(TextFieldTag)
+            .doClick()
+
+        assertAgainstGolden("outlined_textField_focused")
+    }
+
+    @Test
+    fun outlinedTextField_focused_rtl() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag).rtl) {
+                OutlinedTextField(
+                    value = "",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        findByTag(TextFieldTag)
+            .doClick()
+
+        assertAgainstGolden("outlined_textField_focused_rtl")
+    }
+
+    @Test
+    fun filledTextField_withInput() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+                FilledTextField(
+                    value = "Text",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        assertAgainstGolden("filled_textField_withInput")
+    }
+
+    @Test
+    fun filledTextField_notFocused() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+                FilledTextField(
+                    value = "",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        assertAgainstGolden("filled_textField_not_focused")
+    }
+
+    @Test
+    fun filledTextField_focused() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+                FilledTextField(
+                    value = "",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        findByTag(TextFieldTag)
+            .doClick()
+
+        assertAgainstGolden("filled_textField_focused")
+    }
+
+    @Test
+    fun filledTextField_focused_rtl() {
+        composeTestRule.setMaterialContent {
+            Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag).rtl) {
+                FilledTextField(
+                    value = "",
+                    onValueChange = {},
+                    label = { Text("Label") }
+                )
+            }
+        }
+
+        findByTag(TextFieldTag)
+            .doClick()
+
+        assertAgainstGolden("filled_textField_focused_rtl")
+    }
+
+    private fun assertAgainstGolden(goldenIdentifier: String) {
+        findByTag(TextFieldTag)
+            .captureToBitmap()
+            .assertAgainstGolden(screenshotRule, goldenIdentifier)
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/TextFieldTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldTest.kt
similarity index 95%
rename from ui/ui-material/src/androidTest/java/androidx/ui/material/TextFieldTest.kt
rename to ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldTest.kt
index d6a91b9..bee20c7 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/TextFieldTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldTest.kt
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.ui.material
+package androidx.ui.material.textfield
 
 import android.os.Build
 import androidx.compose.Providers
-import androidx.compose.getValue
 import androidx.compose.remember
-import androidx.compose.setValue
 import androidx.compose.state
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
@@ -84,6 +82,14 @@
 import java.util.concurrent.TimeUnit
 import kotlin.math.roundToInt
 import androidx.ui.layout.preferredWidth
+import androidx.ui.material.FilledTextField
+import androidx.ui.material.MaterialTheme
+import androidx.ui.material.OutlinedTextField
+import androidx.ui.material.TextFieldScroller
+import androidx.ui.material.TextFieldScrollerPosition
+import androidx.ui.material.runOnIdleComposeWithDensity
+import androidx.ui.material.setMaterialContent
+import androidx.ui.material.setMaterialContentAndCollectSizes
 
 @MediumTest
 @RunWith(JUnit4::class)
@@ -728,7 +734,11 @@
                 placeholder = {
                     Text("placeholder")
                     assertThat(contentColor())
-                        .isEqualTo(MaterialTheme.colors.onSurface.copy(0.6f))
+                        .isEqualTo(
+                            MaterialTheme.colors.onSurface.copy(
+                                0.6f
+                            )
+                        )
                     assertThat(currentTextStyle()).isEqualTo(MaterialTheme.typography.subtitle1)
                 }
             )
@@ -749,7 +759,11 @@
                 placeholder = {
                     Text("placeholder")
                     assertThat(contentColor())
-                        .isEqualTo(MaterialTheme.colors.onSurface.copy(0.6f))
+                        .isEqualTo(
+                            MaterialTheme.colors.onSurface.copy(
+                                0.6f
+                            )
+                        )
                     assertThat(currentTextStyle()).isEqualTo(MaterialTheme.typography.subtitle1)
                 }
             )
@@ -985,11 +999,19 @@
                     isErrorValue = false,
                     leadingIcon = {
                         assertThat(contentColor())
-                            .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+                            .isEqualTo(
+                                MaterialTheme.colors.onSurface.copy(
+                                    IconColorAlpha
+                                )
+                            )
                     },
                     trailingIcon = {
                         assertThat(contentColor())
-                            .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+                            .isEqualTo(
+                                MaterialTheme.colors.onSurface.copy(
+                                    IconColorAlpha
+                                )
+                            )
                     }
                 )
                 OutlinedTextField(
@@ -999,11 +1021,19 @@
                     isErrorValue = false,
                     leadingIcon = {
                         assertThat(contentColor())
-                            .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+                            .isEqualTo(
+                                MaterialTheme.colors.onSurface.copy(
+                                    IconColorAlpha
+                                )
+                            )
                     },
                     trailingIcon = {
                         assertThat(contentColor())
-                            .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+                            .isEqualTo(
+                                MaterialTheme.colors.onSurface.copy(
+                                    IconColorAlpha
+                                )
+                            )
                     }
                 )
             }
@@ -1021,7 +1051,11 @@
                     isErrorValue = true,
                     leadingIcon = {
                         assertThat(contentColor())
-                            .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+                            .isEqualTo(
+                                MaterialTheme.colors.onSurface.copy(
+                                    IconColorAlpha
+                                )
+                            )
                     },
                     trailingIcon = {
                         assertThat(contentColor()).isEqualTo(MaterialTheme.colors.error)
@@ -1034,7 +1068,11 @@
                     isErrorValue = true,
                     leadingIcon = {
                         assertThat(contentColor())
-                            .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+                            .isEqualTo(
+                                MaterialTheme.colors.onSurface.copy(
+                                    IconColorAlpha
+                                )
+                            )
                     },
                     trailingIcon = {
                         assertThat(contentColor()).isEqualTo(MaterialTheme.colors.error)
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt b/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
index 660fbaa..f5e0760 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
@@ -16,10 +16,8 @@
 package androidx.ui.material
 
 import androidx.compose.Composable
-import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
 import androidx.ui.core.semantics.semantics
-import androidx.ui.foundation.Box
 import androidx.ui.foundation.ContentGravity
 import androidx.ui.foundation.ProvideTextStyle
 import androidx.ui.foundation.shape.corner.CircleShape
@@ -43,14 +41,11 @@
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredHeight
 import androidx.ui.layout.preferredWidth
-import androidx.ui.layout.relativePaddingFrom
-import androidx.ui.text.LastBaseline
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.PxBounds
 import androidx.ui.unit.dp
 import androidx.ui.unit.height
-import androidx.ui.unit.sp
 import androidx.ui.unit.width
 import kotlin.math.sqrt
 
@@ -58,8 +53,10 @@
  * A TopAppBar displays information and actions relating to the current screen and is placed at the
  * top of the screen.
  *
- * This TopAppBar has slots for a title, navigation icon, and actions. Use the other TopAppBar
- * overload for a generic TopAppBar with no restriction on content.
+ * This TopAppBar has slots for a title, navigation icon, and actions. Note that the [title] slot
+ * is inset from the start according to spec - for custom use cases such as horizontally
+ * centering the title, use the other TopAppBar overload for a generic TopAppBar with no
+ * restriction on content.
  *
  * @sample androidx.ui.material.samples.SimpleTopAppBar
  *
@@ -95,12 +92,12 @@
             }
         }
 
-        Box(Modifier.fillMaxHeight().weight(1f).semantics(), gravity = ContentGravity.BottomStart) {
+        Row(
+            Modifier.fillMaxHeight().weight(1f).semantics(),
+            verticalGravity = ContentGravity.CenterVertically
+        ) {
             ProvideTextStyle(value = MaterialTheme.typography.h6) {
-                val baselineOffset = with(DensityAmbient.current) { TitleBaselineOffset.toDp() }
-                Row(Modifier.relativePaddingFrom(LastBaseline, after = baselineOffset)) {
-                    ProvideEmphasis(emphasisLevels.high, title)
-                }
+                ProvideEmphasis(emphasisLevels.high, title)
             }
         }
 
@@ -463,8 +460,6 @@
 // Start inset for the title when there is a navigation icon provided
 private val TitleIconModifier = Modifier.fillMaxHeight()
     .preferredWidth(72.dp - AppBarHorizontalPadding)
-// The baseline distance for the title from the bottom of the app bar
-private val TitleBaselineOffset = 20.sp
 
 private val BottomAppBarElevation = 8.dp
 // TODO: clarify elevation in surface mapping - spec says 0.dp but it appears to have an
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 927aa89..21a9535 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
@@ -131,7 +131,7 @@
                 state = state,
                 onClick = onClick,
                 enabled = enabled,
-                indication = RippleIndication(bounded = false)
+                indication = RippleIndication(bounded = false, radius = CheckboxRippleRadius)
             )
             .padding(CheckboxDefaultPadding),
         enabled = enabled,
@@ -362,6 +362,7 @@
     }
 }
 
+private val CheckboxRippleRadius = 24.dp
 private val CheckboxDefaultPadding = 2.dp
 private val CheckboxSize = 20.dp
 private val StrokeWidth = 2.dp
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt b/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
index 3d11dcd..e420d35 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
@@ -23,17 +23,19 @@
 import androidx.compose.Composable
 import androidx.compose.Immutable
 import androidx.compose.getValue
+import androidx.compose.remember
 import androidx.compose.setValue
 import androidx.compose.state
 import androidx.ui.animation.Transition
 import androidx.ui.core.ContextAmbient
 import androidx.ui.core.DensityAmbient
+import androidx.ui.core.DrawLayerModifier
 import androidx.ui.core.LayoutDirection
 import androidx.ui.core.Modifier
 import androidx.ui.core.Popup
 import androidx.ui.core.PopupPositionProvider
+import androidx.ui.core.TransformOrigin
 import androidx.ui.unit.Position
-import androidx.ui.core.drawLayer
 import androidx.ui.foundation.Box
 import androidx.ui.foundation.ContentGravity
 import androidx.ui.foundation.ProvideTextStyle
@@ -50,7 +52,15 @@
 import androidx.ui.unit.Density
 import androidx.ui.unit.IntOffset
 import androidx.ui.unit.IntSize
+import androidx.ui.unit.PxBounds
 import androidx.ui.unit.dp
+import androidx.ui.unit.height
+import androidx.ui.unit.toOffset
+import androidx.ui.unit.toSize
+import androidx.ui.unit.width
+import kotlin.math.max
+import kotlin.math.min
+
 /**
  * A Material Design [dropdown menu](https://material.io/components/menus#dropdown-menu).
  *
@@ -94,11 +104,15 @@
         toggle()
 
         if (visibleMenu) {
+            var transformOrigin by state { TransformOrigin.Center }
+            val density = DensityAmbient.current
             val popupPositionProvider = DropdownMenuPositionProvider(
                 dropdownOffset,
-                DensityAmbient.current,
+                density,
                 ContextAmbient.current.resources.displayMetrics
-            )
+            ) { parentBounds, menuBounds ->
+                transformOrigin = calculateTransformOrigin(parentBounds, menuBounds, density)
+            }
 
             Popup(
                 isFocusable = true,
@@ -113,18 +127,22 @@
                         visibleMenu = it
                     }
                 ) { state ->
-                    val scale = state[Scale]
-                    val alpha = state[Alpha]
+                    val drawLayer = remember {
+                        MenuDrawLayerModifier(
+                            { state[Scale] },
+                            { state[Alpha] },
+                            { transformOrigin }
+                        )
+                    }
                     Card(
-                        modifier = Modifier
-                            .drawLayer(scaleX = scale, scaleY = scale, alpha = alpha, clip = true)
+                        modifier = drawLayer
                             // Padding to account for the elevation, otherwise it is clipped.
                             .padding(MenuElevation),
                         elevation = MenuElevation
                     ) {
                         @OptIn(ExperimentalLayout::class)
                         Column(
-                            dropdownModifier
+                            modifier = dropdownModifier
                                 .padding(vertical = DropdownMenuVerticalPadding)
                                 .preferredWidth(IntrinsicSize.Max),
                             children = dropdownContent
@@ -197,7 +215,7 @@
 private val DropdownMenuOpenCloseTransition = transitionDefinition {
     state(false) {
         // Menu is dismissed.
-        this[Scale] = 0f
+        this[Scale] = 0.8f
         this[Alpha] = 0f
     }
     state(true) {
@@ -227,6 +245,53 @@
     }
 }
 
+private class MenuDrawLayerModifier(
+    val scaleProvider: () -> Float,
+    val alphaProvider: () -> Float,
+    val transformOriginProvider: () -> TransformOrigin
+) : DrawLayerModifier {
+    override val scaleX: Float get() = scaleProvider()
+    override val scaleY: Float get() = scaleProvider()
+    override val alpha: Float get() = alphaProvider()
+    override val transformOrigin: TransformOrigin get() = transformOriginProvider()
+    override val clip: Boolean = true
+}
+
+private fun calculateTransformOrigin(
+    parentBounds: PxBounds,
+    menuBounds: PxBounds,
+    density: Density
+): TransformOrigin {
+    val inset = with(density) { MenuElevation.toPx() }
+    val realMenuBounds = PxBounds(
+        menuBounds.left + inset,
+        menuBounds.top + inset,
+        menuBounds.right - inset,
+        menuBounds.bottom - inset
+    )
+    val pivotX = when {
+        realMenuBounds.left >= parentBounds.right -> 0f
+        realMenuBounds.right <= parentBounds.left -> 1f
+        else -> {
+            val intersectionCenter =
+                (max(parentBounds.left, realMenuBounds.left) +
+                        min(parentBounds.right, realMenuBounds.right)) / 2
+            (intersectionCenter + inset - menuBounds.left) / menuBounds.width
+        }
+    }
+    val pivotY = when {
+        realMenuBounds.top >= parentBounds.bottom -> 0f
+        realMenuBounds.bottom <= parentBounds.top -> 1f
+        else -> {
+            val intersectionCenter =
+                (max(parentBounds.top, realMenuBounds.top) +
+                        min(parentBounds.bottom, realMenuBounds.bottom)) / 2
+            (intersectionCenter + inset - menuBounds.top) / menuBounds.height
+        }
+    }
+    return TransformOrigin(pivotX, pivotY)
+}
+
 // Menu positioning.
 
 /**
@@ -237,7 +302,8 @@
 internal data class DropdownMenuPositionProvider(
     val contentOffset: Position,
     val density: Density,
-    val displayMetrics: DisplayMetrics
+    val displayMetrics: DisplayMetrics,
+    val onPositionCalculated: (PxBounds, PxBounds) -> Unit = { _, _ -> }
 ) : PopupPositionProvider {
     override fun calculatePosition(
         parentLayoutPosition: IntOffset,
@@ -276,6 +342,16 @@
             it >= 0 && it + realPopupHeight <= displayMetrics.heightPixels
         } ?: toTop
 
+        // TODO(popam, b/159596546): we should probably have androidx.ui.unit.IntBounds instead
+        onPositionCalculated(
+            PxBounds(parentLayoutPosition.toOffset(), parentLayoutSize.toSize()),
+            PxBounds(
+                x.toFloat() - inset,
+                y.toFloat() - inset,
+                x.toFloat() + inset + realPopupWidth,
+                y.toFloat() + inset + realPopupHeight
+            )
+        )
         return IntOffset(x - inset, y - inset)
     }
 }
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 41a3ffe..ed96e0c 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
@@ -339,7 +339,7 @@
                     selected = selected,
                     onClick = onClick,
                     enabled = enabled,
-                    indication = RippleIndication(bounded = false)
+                    indication = RippleIndication(bounded = false, radius = RadioButtonRippleRadius)
                 )
                 .wrapContentSize(Alignment.Center)
                 .padding(RadioButtonPadding)
@@ -409,6 +409,7 @@
         }
     }
 
+private val RadioButtonRippleRadius = 24.dp
 private val RadioButtonPadding = 2.dp
 private val RadioButtonSize = 20.dp
 private val RadioRadius = RadioButtonSize / 2
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 df8fec0..8425445 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
@@ -254,7 +254,7 @@
             center.y
         )
 
-        drawLine(color, sliderStart, sliderValue, trackStrokeWidth)
+        drawLine(color, sliderStart, sliderValue, trackStrokeWidth, StrokeCap.round)
         tickFractions.groupBy { it > positionFraction }.forEach { (afterFraction, list) ->
             drawPoints(
                 list.map {
@@ -262,7 +262,8 @@
                 },
                 PointMode.points,
                 if (afterFraction) inactiveTickColor else activeTickColor,
-                trackStrokeWidth
+                trackStrokeWidth,
+                StrokeCap.round
             )
         }
     }
@@ -451,16 +452,21 @@
         }
 }
 
-private val ThumbRadius = 10.dp
+// Internal to be referred to in tests
+internal val ThumbRadius = 10.dp
 private val ThumbRippleRadius = 24.dp
 private val ThumbDefaultElevation = 1.dp
 private val ThumbPressedElevation = 6.dp
-private val TrackHeight = 4.dp
+
+// Internal to be referred to in tests
+internal val TrackHeight = 4.dp
 private val SliderHeight = 48.dp
 private val SliderMinWidth = 144.dp // TODO: clarify min width
 private val DefaultSliderConstraints =
     Modifier.preferredWidthIn(minWidth = SliderMinWidth)
         .preferredHeightIn(maxHeight = SliderHeight)
-private val InactiveTrackColorAlpha = 0.24f
+
+// Internal to be referred to in tests
+internal val InactiveTrackColorAlpha = 0.24f
 private val TickColorAlpha = 0.54f
 private val SliderToTickAnimation = TweenBuilder<Float>().apply { duration = 100 }
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 ba5f936..fa43067 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
@@ -19,20 +19,35 @@
 import androidx.animation.TweenBuilder
 import androidx.compose.Composable
 import androidx.compose.State
+import androidx.compose.remember
 import androidx.compose.state
+import androidx.ui.core.Alignment
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.Modifier
 import androidx.ui.core.semantics.semantics
-import androidx.ui.foundation.Box
 import androidx.ui.foundation.Canvas
+import androidx.ui.foundation.Interaction
+import androidx.ui.foundation.InteractionState
 import androidx.ui.foundation.gestures.DragDirection
+import androidx.ui.foundation.indication
 import androidx.ui.foundation.selection.toggleable
+import androidx.ui.foundation.shape.corner.CircleShape
 import androidx.ui.geometry.Offset
 import androidx.ui.graphics.Color
 import androidx.ui.graphics.StrokeCap
+import androidx.ui.graphics.compositeOver
 import androidx.ui.graphics.drawscope.DrawScope
+import androidx.ui.layout.Stack
+import androidx.ui.layout.StackScope
+import androidx.ui.layout.offsetPx
 import androidx.ui.layout.padding
 import androidx.ui.layout.preferredSize
+import androidx.ui.material.SwitchDefaults.disabledUncheckedThumbColor
+import androidx.ui.material.SwitchDefaults.disabledUncheckedTrackColor
+import androidx.ui.material.SwitchDefaults.makeDisabledCheckedThumbColor
+import androidx.ui.material.SwitchDefaults.makeDisabledCheckedTrackColor
+import androidx.ui.material.SwitchDefaults.uncheckedThumbColor
+import androidx.ui.material.SwitchDefaults.uncheckedTrackColor
 import androidx.ui.material.internal.stateDraggable
 import androidx.ui.material.ripple.RippleIndication
 import androidx.ui.unit.dp
@@ -47,7 +62,7 @@
  * therefore the change of checked state is requested.
  * @param modifier Modifier to be applied to the switch layout
  * @param enabled whether or not components is enabled and can be clicked to request state change
- * @param color active color for Switch
+ * @param color main color of the track and trumb when the Switch is checked
  */
 @Composable
 fun Switch(
@@ -60,14 +75,16 @@
     val minBound = 0f
     val maxBound = with(DensityAmbient.current) { ThumbPathLength.toPx() }
     val thumbPosition = state { if (checked) maxBound else minBound }
-    Box(
+    val interactionState = remember { InteractionState() }
+    Stack(
         modifier
             .semantics(mergeAllDescendants = true)
             .toggleable(
                 value = checked,
                 onValueChange = onCheckedChange,
                 enabled = enabled,
-                indication = RippleIndication(bounded = false)
+                interactionState = interactionState,
+                indication = null
             )
             .stateDraggable(
                 state = checked,
@@ -77,35 +94,56 @@
                 dragDirection = DragDirection.Horizontal,
                 minValue = minBound,
                 maxValue = maxBound,
+                enabled = enabled,
+                interactionState = interactionState,
                 onNewValue = { thumbPosition.value = it }
             )
             .padding(DefaultSwitchPadding)
     ) {
-        DrawSwitch(
+        SwitchImpl(
             checked = checked,
-            checkedThumbColor = color,
-            thumbValue = thumbPosition
+            enabled = enabled,
+            checkedColor = color,
+            thumbValue = thumbPosition,
+            interactionState = interactionState
         )
     }
 }
 
 @Composable
-private fun DrawSwitch(
+private fun StackScope.SwitchImpl(
     checked: Boolean,
-    checkedThumbColor: Color,
-    thumbValue: State<Float>
+    enabled: Boolean,
+    checkedColor: Color,
+    thumbValue: State<Float>,
+    interactionState: InteractionState
 ) {
-    val thumbColor = if (checked) checkedThumbColor else MaterialTheme.colors.surface
-    val trackColor = if (checked) {
-        checkedThumbColor.copy(alpha = CheckedTrackOpacity)
-    } else {
-        MaterialTheme.colors.onSurface.copy(alpha = UncheckedTrackOpacity)
-    }
-
-    Canvas(Modifier.preferredSize(SwitchWidth, SwitchHeight)) {
+    val hasInteraction =
+        Interaction.Pressed in interactionState || Interaction.Dragged in interactionState
+    val elevation =
+        if (hasInteraction) {
+            SwitchDefaults.ThumbPressedElevation
+        } else {
+            SwitchDefaults.ThumbDefaultElevation
+        }
+    val trackColor = SwitchDefaults.resolveTrackColor(checked, enabled, checkedColor)
+    val thumbColor = SwitchDefaults.resolveThumbColor(checked, enabled, checkedColor)
+    Canvas(Modifier.gravity(Alignment.Center).preferredSize(SwitchWidth, SwitchHeight)) {
         drawTrack(trackColor, TrackWidth.toPx(), TrackStrokeWidth.toPx())
-        drawThumb(thumbValue.value, ThumbDiameter.toPx(), thumbColor)
     }
+    Surface(
+        shape = CircleShape,
+        color = thumbColor,
+        elevation = elevation,
+        modifier = Modifier
+            .gravity(Alignment.CenterStart)
+            .offsetPx(x = thumbValue)
+            .indication(
+                interactionState = interactionState,
+                indication = RippleIndication(radius = ThumbRippleRadius, bounded = false)
+            )
+            .preferredSize(ThumbDiameter)
+    ) {}
 }
 
 private fun DrawScope.drawTrack(trackColor: Color, trackWidth: Float, strokeWidth: Float) {
@@ -119,24 +157,74 @@
     )
 }
 
-private fun DrawScope.drawThumb(position: Float, thumbDiameter: Float, thumbColor: Color) {
-    val thumbRadius = thumbDiameter / 2
-    val x = position + thumbRadius
-    drawCircle(thumbColor, thumbRadius, Offset(x, center.y))
-}
+internal val TrackWidth = 34.dp
+internal val TrackStrokeWidth = 14.dp
+internal val ThumbDiameter = 20.dp
 
-private const val CheckedTrackOpacity = 0.54f
-private const val UncheckedTrackOpacity = 0.38f
+private val ThumbRippleRadius = 24.dp
 
-private val TrackWidth = 34.dp
-private val TrackStrokeWidth = 14.dp
-
-private val ThumbDiameter = 20.dp
-
-// TODO(malkov): clarify this padding for Switch
 private val DefaultSwitchPadding = 2.dp
 private val SwitchWidth = TrackWidth
 private val SwitchHeight = ThumbDiameter
 private val ThumbPathLength = TrackWidth - ThumbDiameter
 
 private val AnimationBuilder = TweenBuilder<Float>().apply { duration = 100 }
+
+internal object SwitchDefaults {
+
+    const val CheckedTrackOpacity = 0.54f
+    const val UncheckedTrackOpacity = 0.38f
+
+    val ThumbDefaultElevation = 1.dp
+    val ThumbPressedElevation = 6.dp
+
+    @Composable
+    private val uncheckedTrackColor
+        get() = MaterialTheme.colors.onSurface
+
+    @Composable
+    private fun makeDisabledCheckedTrackColor(checkedColor: Color) = EmphasisAmbient.current
+        .disabled
+        .applyEmphasis(checkedColor)
+        .compositeOver(MaterialTheme.colors.surface)
+
+    @Composable
+    private val disabledUncheckedTrackColor
+        get() = EmphasisAmbient.current.disabled.applyEmphasis(MaterialTheme.colors.onSurface)
+            .compositeOver(MaterialTheme.colors.surface)
+
+    @Composable
+    private val uncheckedThumbColor
+        get() = MaterialTheme.colors.surface
+
+    @Composable
+    private fun makeDisabledCheckedThumbColor(checkedColor: Color) = EmphasisAmbient.current
+        .disabled
+        .applyEmphasis(checkedColor)
+        .compositeOver(MaterialTheme.colors.surface)
+
+    @Composable
+    private val disabledUncheckedThumbColor
+        get() = EmphasisAmbient.current.disabled.applyEmphasis(MaterialTheme.colors.surface)
+            .compositeOver(MaterialTheme.colors.surface)
+
+    @Composable
+    internal fun resolveTrackColor(checked: Boolean, enabled: Boolean, checkedColor: Color): Color {
+        return if (checked) {
+            val color = if (enabled) checkedColor else makeDisabledCheckedTrackColor(checkedColor)
+            color.copy(alpha = CheckedTrackOpacity)
+        } else {
+            val color = if (enabled) uncheckedTrackColor else disabledUncheckedTrackColor
+            color.copy(alpha = UncheckedTrackOpacity)
+        }
+    }
+
+    @Composable
+    internal fun resolveThumbColor(checked: Boolean, enabled: Boolean, checkedColor: Color): Color {
+        return if (checked) {
+            if (enabled) checkedColor else makeDisabledCheckedThumbColor(checkedColor)
+        } else {
+            if (enabled) uncheckedThumbColor else disabledUncheckedThumbColor
+        }
+    }
+}
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 0b17914..323d931 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
@@ -82,10 +82,11 @@
 import androidx.ui.material.ripple.RippleIndication
 import androidx.ui.savedinstancestate.Saver
 import androidx.ui.savedinstancestate.rememberSavedInstanceState
+import androidx.ui.text.InternalTextApi
 import androidx.ui.text.LastBaseline
 import androidx.ui.text.SoftwareKeyboardController
-import androidx.ui.text.TextRange
 import androidx.ui.text.TextStyle
+import androidx.ui.text.constrain
 import androidx.ui.text.lerp
 import androidx.ui.unit.Dp
 import androidx.ui.unit.IntSize
@@ -202,11 +203,11 @@
 ) {
     var textFieldValue by state { TextFieldValue() }
     if (textFieldValue.text != value) {
-        val newSelection = TextRange(
-            textFieldValue.selection.start.coerceIn(0, value.length),
-            textFieldValue.selection.end.coerceIn(0, value.length)
+        @OptIn(InternalTextApi::class)
+        textFieldValue = TextFieldValue(
+            text = value,
+            selection = textFieldValue.selection.constrain(0, value.length)
         )
-        textFieldValue = TextFieldValue(text = value, selection = newSelection)
     }
     TextFieldImpl(
         type = TextFieldType.Filled,
@@ -375,13 +376,10 @@
 
     val fullModel = state { TextFieldValue() }
     if (fullModel.value.text != value.text || fullModel.value.selection != value.selection) {
-        val newSelection = TextRange(
-            value.selection.start.coerceIn(0, value.text.length),
-            value.selection.end.coerceIn(0, value.text.length)
-        )
+        @OptIn(InternalTextApi::class)
         fullModel.value = TextFieldValue(
             text = value.text,
-            selection = newSelection
+            selection = value.selection.constrain(0, value.text.length)
         )
     }
 
@@ -500,11 +498,10 @@
 ) {
     var textFieldValue by state { TextFieldValue() }
     if (textFieldValue.text != value) {
-        val newSelection = TextRange(
-            textFieldValue.selection.start.coerceIn(0, value.length),
-            textFieldValue.selection.end.coerceIn(0, value.length)
-        )
-        textFieldValue = TextFieldValue(text = value, selection = newSelection)
+        @OptIn(InternalTextApi::class)
+        textFieldValue = TextFieldValue(
+            text = value,
+            selection = textFieldValue.selection.constrain(0, value.length))
     }
 
     TextFieldImpl(
@@ -1510,9 +1507,15 @@
         } else {
             val effectivePadding = padding - innerPadding - dx - lineWidth / 2
             val gap = diff + 2 * innerPadding
-            relativeLineTo(-effectiveWidth + effectivePadding + gap, 0f)
-            relativeMoveTo(-gap, 0f)
-            relativeLineTo(-effectivePadding, 0f)
+            if (layoutDirection == LayoutDirection.Ltr) {
+                relativeLineTo(-effectiveWidth + effectivePadding + gap, 0f)
+                relativeMoveTo(-gap, 0f)
+                relativeLineTo(-effectivePadding, 0f)
+            } else {
+                relativeLineTo(-effectivePadding, 0f)
+                relativeMoveTo(-gap, 0f)
+                relativeLineTo(-effectiveWidth + gap + effectivePadding, 0f)
+            }
         }
 
         // top-left corner and left line
diff --git a/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt b/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt
index 7955232..ffab1e3 100644
--- a/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt
+++ b/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt
@@ -17,7 +17,6 @@
 package androidx.ui.rxjava2
 
 import androidx.compose.Composable
-import androidx.compose.Composer
 import androidx.compose.FrameManager
 import androidx.compose.State
 import androidx.compose.onPreCommit
@@ -197,17 +196,3 @@
     }
     return state
 }
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
-    "This property should not be called directly. It is only used by the compiler.",
-    replaceWith = ReplaceWith("currentComposer")
-)
-internal val composer: Composer<*>
-    get() = error(
-        "This property should not be called directly. It is only used by the compiler."
-    )
diff --git a/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt b/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
index e7d7037..8dee58a 100644
--- a/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
+++ b/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
@@ -16,7 +16,6 @@
 
 package androidx.ui.savedinstancestate
 
-import androidx.compose.Composer
 import androidx.compose.staticAmbientOf
 
 /**
@@ -121,18 +120,4 @@
         }
         return map
     }
-}
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
-    "This property should not be called directly. It is only used by the compiler.",
-    replaceWith = ReplaceWith("currentComposer")
-)
-internal val composer: Composer<*>
-    get() = error(
-        "This property should not be called directly. It is only used by the compiler."
-    )
+}
\ No newline at end of file
diff --git a/ui/ui-test/api/0.1.0-dev15.txt b/ui/ui-test/api/0.1.0-dev15.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/0.1.0-dev15.txt
+++ b/ui/ui-test/api/0.1.0-dev15.txt
@@ -64,8 +64,11 @@
   public final class BoundsAssertionsKt {
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+    method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+    method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+    method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
   }
 
   public final class CollectedSizes {
@@ -297,7 +300,7 @@
     method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
     method public operator androidx.ui.test.SemanticsMatcher not();
     method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
-    field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+    field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
   }
 
   public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/current.txt b/ui/ui-test/api/current.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/current.txt
+++ b/ui/ui-test/api/current.txt
@@ -64,8 +64,11 @@
   public final class BoundsAssertionsKt {
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+    method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+    method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+    method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
   }
 
   public final class CollectedSizes {
@@ -297,7 +300,7 @@
     method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
     method public operator androidx.ui.test.SemanticsMatcher not();
     method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
-    field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+    field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
   }
 
   public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt
@@ -64,8 +64,11 @@
   public final class BoundsAssertionsKt {
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+    method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+    method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+    method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
   }
 
   public final class CollectedSizes {
@@ -297,7 +300,7 @@
     method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
     method public operator androidx.ui.test.SemanticsMatcher not();
     method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
-    field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+    field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
   }
 
   public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/public_plus_experimental_current.txt b/ui/ui-test/api/public_plus_experimental_current.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/public_plus_experimental_current.txt
+++ b/ui/ui-test/api/public_plus_experimental_current.txt
@@ -64,8 +64,11 @@
   public final class BoundsAssertionsKt {
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+    method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+    method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+    method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
   }
 
   public final class CollectedSizes {
@@ -297,7 +300,7 @@
     method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
     method public operator androidx.ui.test.SemanticsMatcher not();
     method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
-    field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+    field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
   }
 
   public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/restricted_0.1.0-dev15.txt b/ui/ui-test/api/restricted_0.1.0-dev15.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-test/api/restricted_0.1.0-dev15.txt
@@ -64,8 +64,11 @@
   public final class BoundsAssertionsKt {
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+    method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+    method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+    method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
   }
 
   public final class CollectedSizes {
@@ -297,7 +300,7 @@
     method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
     method public operator androidx.ui.test.SemanticsMatcher not();
     method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
-    field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+    field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
   }
 
   public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/restricted_current.txt b/ui/ui-test/api/restricted_current.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/restricted_current.txt
+++ b/ui/ui-test/api/restricted_current.txt
@@ -64,8 +64,11 @@
   public final class BoundsAssertionsKt {
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
     method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+    method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
     method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+    method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+    method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
   }
 
   public final class CollectedSizes {
@@ -297,7 +300,7 @@
     method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
     method public operator androidx.ui.test.SemanticsMatcher not();
     method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
-    field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+    field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
   }
 
   public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
index 7867b1b..4a2ceb7 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
@@ -25,6 +25,7 @@
 import androidx.ui.semantics.accessibilityLabel
 import androidx.ui.semantics.testTag
 import androidx.ui.semantics.text
+import androidx.ui.test.util.expectError
 import androidx.ui.text.AnnotatedString
 import org.junit.Rule
 import org.junit.Test
@@ -112,14 +113,16 @@
         findBySubstring("world", ignoreCase = true)
     }
 
-    @Test(expected = AssertionError::class)
+    @Test
     fun findBySubstring_wrongCase_fails() {
         composeTestRule.setContent {
             BoundaryNode { text = AnnotatedString("Hello World") }
         }
 
-        // Need to assert exists or it won't fail
-        findBySubstring("world").assertExists()
+        expectError<AssertionError> {
+            // Need to assert exists or it won't fetch nodes
+            findBySubstring("world").assertExists()
+        }
     }
 
     @Composable
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
index aa24a07f..9c4369f 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.test.filters.MediumTest
 import androidx.ui.test.android.AndroidOwnerRegistry
+import androidx.ui.test.util.expectError
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -71,6 +72,39 @@
         }
     }
 
+    @Test
+    fun runOnIdleCompose_assert_fails() {
+        withAndroidOwnerRegistry {
+            runOnIdleCompose {
+                expectError<IllegalStateException> {
+                    findByTag("dummy").assertExists()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun runOnIdleCompose_waitForIdle_fails() {
+        withAndroidOwnerRegistry {
+            runOnIdleCompose {
+                expectError<IllegalStateException> {
+                    waitForIdle()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun runOnIdleCompose_runOnIdleCompose_fails() {
+        withAndroidOwnerRegistry {
+            runOnIdleCompose {
+                expectError<IllegalStateException> {
+                    runOnIdleCompose {}
+                }
+            }
+        }
+    }
+
     private fun withAndroidOwnerRegistry(block: () -> Unit) {
         AndroidOwnerRegistry.setupRegistry()
         try {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt
index 0cbe1b7..64a2ccd 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt
@@ -24,10 +24,12 @@
 import androidx.ui.foundation.drawBackground
 import androidx.ui.graphics.Color
 import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.padding
 import androidx.ui.layout.size
 import androidx.ui.layout.wrapContentSize
 import androidx.ui.test.assertHeightIsAtLeast
 import androidx.ui.test.assertHeightIsEqualTo
+import androidx.ui.test.assertPositionInRootIsEqualTo
 import androidx.ui.test.assertWidthIsAtLeast
 import androidx.ui.test.assertWidthIsEqualTo
 import androidx.ui.test.createComposeRule
@@ -52,13 +54,15 @@
         composeTestRule.setContent {
             Box(modifier = Modifier
                 .fillMaxSize()
-                .wrapContentSize(Alignment.Center)
+                .wrapContentSize(Alignment.TopStart)
             ) {
-                Box(modifier = Modifier
-                    .testTag(tag)
-                    .size(80.dp, 100.dp)
-                    .drawBackground(Color.Black)
-                )
+                Box(modifier = Modifier.padding(start = 50.dp, top = 100.dp)) {
+                    Box(modifier = Modifier
+                        .testTag(tag)
+                        .size(80.dp, 100.dp)
+                        .drawBackground(Color.Black)
+                    )
+                }
             }
         }
     }
@@ -112,4 +116,27 @@
                 .assertHeightIsAtLeast(101.dp)
         }
     }
+
+    @Test
+    fun assertPosition() {
+        composeBox()
+
+        findByTag(tag)
+            .assertPositionInRootIsEqualTo(expectedLeft = 50.dp, expectedTop = 100.dp)
+    }
+
+    @Test
+    fun assertPosition_fail() {
+        composeBox()
+
+        expectError<AssertionError> {
+            findByTag(tag)
+                .assertPositionInRootIsEqualTo(expectedLeft = 51.dp, expectedTop = 101.dp)
+        }
+
+        expectError<AssertionError> {
+            findByTag(tag)
+                .assertPositionInRootIsEqualTo(expectedLeft = 49.dp, expectedTop = 99.dp)
+        }
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt
index 2accc7a..645898e 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt
@@ -16,39 +16,75 @@
 
 package androidx.ui.test.util
 
-import com.google.common.truth.Truth.assertWithMessage
 import java.io.PrintWriter
 import java.io.StringWriter
+import kotlin.text.RegexOption.DOT_MATCHES_ALL
 
 /**
- * Runs the [block] and asserts that an [AssertionError] is thrown if [expectError] is `true`, or
- * that it is not thrown if [expectError] is `false`.
+ * Runs the [block] and asserts that a [AssertionError] is thrown with the [expectedMessage] if
+ * [expectError] is `true`, or that nothing is thrown if [expectError] is `false`. The
+ * [expectedMessage] is a regex with just the option [DOT_MATCHES_ALL] enabled.
  */
-fun expectAssertionError(expectError: Boolean, block: () -> Unit) {
-    expectError<AssertionError>(expectError, block)
+fun expectAssertionError(
+    expectError: Boolean,
+    expectedMessage: String = ".*",
+    block: () -> Unit
+) {
+    expectError<AssertionError>(expectError, expectedMessage, block)
 }
 
 /**
- * Runs the [block] and asserts that a [T] is thrown if [expectError] is `true`, or that it is
- * not thrown if [expectError] is `false`.
+ * Runs the [block] and asserts that a [T] is thrown with the [expectedMessage] if [expectError]
+ * is `true`, or that nothing is thrown if [expectError] is `false`. The [expectedMessage] is a
+ * regex with just the option [DOT_MATCHES_ALL] enabled.
  */
-inline fun <reified T : Throwable> expectError(expectError: Boolean = true, block: () -> Unit) {
-    var thrown = false
-    val errorClassName = T::class.java.simpleName
-    var errorMessage = "Expected a $errorClassName, got nothing"
+inline fun <reified T : Throwable> expectError(
+    expectError: Boolean = true,
+    expectedMessage: String = ".*",
+    block: () -> Unit
+) {
+    val expectedClassName = T::class.java.simpleName
     try {
         block()
-    } catch (t: Throwable) {
-        if (t !is T) {
-            throw t
+    } catch (thrown: Throwable) {
+        if (!expectError) {
+            throwExpectError(null, thrown)
+        } else if (thrown !is T) {
+            throwExpectError(expectedClassName, thrown)
+        } else if (!expectedMessage.toRegex(DOT_MATCHES_ALL).matches(thrown.message ?: "")) {
+            throwExpectError(expectedClassName, thrown, expectedMessage)
         }
-        thrown = true
+        // Thrown error matched what was expected
+        return
+    }
+    if (expectError) {
+        // Nothing was thrown, but we did expect it
+        throwExpectError(expectedClassName)
+    }
+}
+
+@PublishedApi
+internal fun throwExpectError(
+    expectedClassName: String?,
+    thrown: Throwable? = null,
+    expectedMessage: String? = null
+) {
+    val stackTrace = thrown?.let {
         StringWriter().use { sw ->
             PrintWriter(sw).use { pw ->
-                t.printStackTrace(pw)
+                it.printStackTrace(pw)
             }
-            errorMessage = "Expected no $errorClassName, got:\n==============\n$sw=============="
+            ":\n==============================\n$sw=============================="
         }
+    } ?: ""
+
+    fun String.plusMessage(message: String?): String {
+        return if (expectedMessage == null) this else "$this with message \"$message\""
     }
-    assertWithMessage(errorMessage).that(thrown).isEqualTo(expectError)
+
+    val expected = expectedClassName?.let { "a $it".plusMessage(expectedMessage) } ?: "nothing"
+    val actual = thrown?.run { "a ${javaClass.simpleName}".plusMessage(message) } ?: "nothing"
+    throw AssertionError(
+        "Expected that $expected was thrown, but $actual was thrown$stackTrace"
+    )
 }
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ExpectTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ExpectTest.kt
new file mode 100644
index 0000000..999b1fb
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ExpectTest.kt
@@ -0,0 +1,126 @@
+/*
+ * 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.util
+
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+
+class ExpectTest {
+
+    class TestException(message: String? = null) : Exception(message)
+
+    @Test
+    fun expectError_gotError() {
+        expectError<TestException> {
+            throw TestException()
+        }
+    }
+
+    @Test
+    fun expectError_gotErrorWithMessage() {
+        expectError<TestException> {
+            throw TestException("message")
+        }
+    }
+
+    @Test
+    fun expectError_gotErrorWithMultilineMessage() {
+        expectError<TestException> {
+            throw TestException("message\nwith 2 lines")
+        }
+    }
+
+    @Test
+    fun expectError_gotNothing() {
+        expectErrorMessage(
+            "Expected that a TestException was thrown, but nothing was thrown"
+        ) {
+            expectError<TestException> {
+            }
+        }
+    }
+
+    @Test
+    fun expectError_gotDifferentError() {
+        expectErrorMessage(
+            "Expected that a TestException was thrown, but a IllegalStateException was thrown:\n=="
+        ) {
+            expectError<TestException> {
+                throw IllegalStateException()
+            }
+        }
+    }
+
+    @Test
+    fun expectNoError_gotNoError() {
+        expectError<TestException>(false) {
+        }
+    }
+
+    @Test
+    fun expectNoError_gotError() {
+        expectErrorMessage(
+            "Expected that nothing was thrown, but a TestException was thrown:\n=="
+        ) {
+            expectError<TestException>(false) {
+                throw TestException()
+            }
+        }
+    }
+
+    @Test
+    fun expectNoError_gotDifferentError() {
+        expectErrorMessage(
+            "Expected that nothing was thrown, but a IllegalStateException was thrown:\n=="
+        ) {
+            expectError<TestException>(false) {
+                throw IllegalStateException()
+            }
+        }
+    }
+
+    @Test
+    fun expectErrorWithMessage_gotErrorWithMessage() {
+        expectError<TestException>(expectedMessage = "message") {
+            throw TestException("message")
+        }
+    }
+
+    @Test
+    fun expectErrorWithMessage_gotErrorWithDifferentMessage() {
+        expectErrorMessage(
+            "Expected that a TestException with message \"message\" was thrown, " +
+                    "but a TestException with message \"message x\" was thrown:\n=="
+        ) {
+            expectError<TestException>(expectedMessage = "message") {
+                throw TestException("message x")
+            }
+        }
+    }
+
+    private fun expectErrorMessage(expectedErrorMessage: String, block: () -> Unit) {
+        try {
+            block()
+        } catch (e: AssertionError) {
+            assertWithMessage("expectError threw an AssertionError with the wrong message")
+                .that(e.message)
+                .startsWith(expectedErrorMessage)
+            return
+        }
+        throw AssertionError("Expected an AssertionError, but it wasn't thrown")
+    }
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt b/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt
index 2205c8ce..a16fd1f 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt
@@ -16,7 +16,10 @@
 
 package androidx.ui.test
 
+import androidx.ui.core.AlignmentLine
 import androidx.ui.core.AndroidOwner
+import androidx.ui.core.semantics.SemanticsNode
+import androidx.ui.unit.Bounds
 import androidx.ui.unit.Density
 import androidx.ui.unit.Dp
 import androidx.ui.unit.PxBounds
@@ -71,6 +74,64 @@
     }
 }
 
+/**
+* Returns the bounds of the layout of this node. The bounds are relative to the root composable.
+*/
+fun SemanticsNodeInteraction.getBoundsInRoot(): Bounds {
+    lateinit var bounds: Bounds
+    withBoundsInRoot {
+        bounds = Bounds(
+            left = it.left.toDp(),
+            top = it.top.toDp(),
+            right = it.right.toDp(),
+            bottom = it.bottom.toDp()
+        )
+    }
+    return bounds
+}
+
+/**
+ * Asserts that the layout of this node has position in the root composable that is equal to the
+ * given position.
+ *
+ * @param expectedLeft The left (x) position to assert.
+ * @param expectedTop The top (y) position to assert.
+ *
+ * @throws AssertionError if comparison fails.
+ */
+fun SemanticsNodeInteraction.assertPositionInRootIsEqualTo(
+    expectedLeft: Dp,
+    expectedTop: Dp
+): SemanticsNodeInteraction {
+    return withBoundsInRoot {
+        areEqualOrThrow("left", it.left, expectedLeft)
+        areEqualOrThrow("top", it.top, expectedTop)
+    }
+}
+
+/**
+ * Returns the position of an [alignment line][AlignmentLine], or [Dp.Unspecified] if the line is
+ * not provided.
+ */
+fun SemanticsNodeInteraction.getAlignmentLinePosition(line: AlignmentLine): Dp {
+    return withDensity {
+        val pos = it.getAlignmentLinePosition(line)
+        if (pos == AlignmentLine.Unspecified) {
+            Dp.Unspecified
+        } else {
+            pos.toDp()
+        }
+    }
+}
+
+private fun <R> SemanticsNodeInteraction.withDensity(
+    operation: Density.(SemanticsNode) -> R
+): R {
+    val node = fetchSemanticsNode("Failed to retrieve density for the node.")
+    val density = (node.componentNode.owner as AndroidOwner).density
+    return operation.invoke(density, node)
+}
+
 private fun SemanticsNodeInteraction.withBoundsInRoot(
     assertion: Density.(PxBounds) -> Unit
 ): SemanticsNodeInteraction {
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
index fd004f0..8a9d311 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
@@ -16,9 +16,6 @@
 
 package androidx.ui.test
 
-import androidx.ui.core.semantics.SemanticsNode
-import androidx.ui.test.android.SynchronizedTreeCollector
-
 /**
  * Finds a component identified by the given tag.
  *
@@ -115,7 +112,3 @@
 fun findAll(matcher: SemanticsMatcher): SemanticsNodeInteractionCollection {
     return SemanticsNodeInteractionCollection(SemanticsSelector(matcher))
 }
-
-internal fun getAllSemanticsNodes(): List<SemanticsNode> {
-    return SynchronizedTreeCollector.collectAllSemanticsNodes()
-}
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt b/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt
index 1e515ea..f46084a 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt
@@ -17,6 +17,7 @@
 package androidx.ui.test
 
 import androidx.ui.core.semantics.SemanticsNode
+import androidx.ui.test.android.SynchronizedTreeCollector.getAllSemanticsNodes
 
 /**
  * Represents a semantics node and the path to fetch it from the semantics tree. One can interact
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt
index a7d8174..deba7ae 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt
@@ -30,9 +30,9 @@
 import android.widget.ImageView
 import androidx.activity.ComponentActivity
 import androidx.compose.Composition
-import androidx.compose.CompositionFrameClock
 import androidx.compose.FrameManager
 import androidx.compose.Recomposer
+import androidx.compose.dispatch.MonotonicFrameClock
 import androidx.compose.frames.currentFrame
 import androidx.compose.frames.inFrame
 import androidx.ui.core.AndroidOwner
@@ -83,7 +83,7 @@
 
     private class AutoFrameClock(
         private val singleFrameTimeNanos: Long = 16_000_000
-    ) : CompositionFrameClock {
+    ) : MonotonicFrameClock {
         private val lastFrameTime = AtomicLong(0L)
 
         override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R =
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
index 5e95c72..5e90b97 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
@@ -43,7 +43,7 @@
      * Can crash in case Espresso hits time out. This is not supposed to be handled as it
      * surfaces only in incorrect tests.
      */
-    internal fun collectAllSemanticsNodes(): List<SemanticsNode> {
+    internal fun getAllSemanticsNodes(): List<SemanticsNode> {
         ensureAndroidOwnerRegistryIsSetUp()
 
         // TODO(pavlis): Instead of returning a flatMap, let all consumers handle a tree
@@ -65,6 +65,13 @@
      * surfaces only in incorrect tests.
      */
     internal fun waitForIdle() {
+        check(!isOnUiThread()) {
+            "Functions that involve synchronization (Assertions, Actions, Synchronization; " +
+                    "e.g. assertIsSelected(), doClick(), runOnIdleCompose()) cannot be run " +
+                    "from the main thread. Did you nest such a function inside " +
+                    "runOnIdleCompose {}, runOnUiThread {} or setContent {}?"
+        }
+
         registerComposeWithEspresso()
         // First wait for Android mechanisms to settle down
         Espresso.onIdle()
diff --git a/ui/ui-text-android/api/0.1.0-dev15.txt b/ui/ui-text-android/api/0.1.0-dev15.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/0.1.0-dev15.txt
+++ b/ui/ui-text-android/api/0.1.0-dev15.txt
@@ -7,6 +7,9 @@
   public final class LayoutCompatKt {
   }
 
+  public final class LayoutHelperKt {
+  }
+
   public final class LayoutIntrinsicsKt {
   }
 
diff --git a/ui/ui-text-android/api/current.txt b/ui/ui-text-android/api/current.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/current.txt
+++ b/ui/ui-text-android/api/current.txt
@@ -7,6 +7,9 @@
   public final class LayoutCompatKt {
   }
 
+  public final class LayoutHelperKt {
+  }
+
   public final class LayoutIntrinsicsKt {
   }
 
diff --git a/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt
@@ -7,6 +7,9 @@
   public final class LayoutCompatKt {
   }
 
+  public final class LayoutHelperKt {
+  }
+
   public final class LayoutIntrinsicsKt {
   }
 
diff --git a/ui/ui-text-android/api/public_plus_experimental_current.txt b/ui/ui-text-android/api/public_plus_experimental_current.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-android/api/public_plus_experimental_current.txt
@@ -7,6 +7,9 @@
   public final class LayoutCompatKt {
   }
 
+  public final class LayoutHelperKt {
+  }
+
   public final class LayoutIntrinsicsKt {
   }
 
diff --git a/ui/ui-text-android/api/restricted_0.1.0-dev15.txt b/ui/ui-text-android/api/restricted_0.1.0-dev15.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-text-android/api/restricted_0.1.0-dev15.txt
@@ -7,6 +7,9 @@
   public final class LayoutCompatKt {
   }
 
+  public final class LayoutHelperKt {
+  }
+
   public final class LayoutIntrinsicsKt {
   }
 
diff --git a/ui/ui-text-android/api/restricted_current.txt b/ui/ui-text-android/api/restricted_current.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/restricted_current.txt
+++ b/ui/ui-text-android/api/restricted_current.txt
@@ -7,6 +7,9 @@
   public final class LayoutCompatKt {
   }
 
+  public final class LayoutHelperKt {
+  }
+
   public final class LayoutIntrinsicsKt {
   }
 
diff --git a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/LayoutHelperParagraphTest.kt b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/LayoutHelperParagraphTest.kt
new file mode 100644
index 0000000..f07fb09
--- /dev/null
+++ b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/LayoutHelperParagraphTest.kt
@@ -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.ui.text.platform
+
+import android.os.Build
+import android.text.Layout
+import android.text.StaticLayout
+import android.text.TextPaint
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@OptIn(InternalPlatformTextApi::class)
+@RunWith(JUnit4::class)
+class LayoutHelperParagraphTest {
+
+    private val WIDTH = 100
+    private val TEXT_PAINT = TextPaint()
+
+    private fun buildLayoutHelper(text: String): LayoutHelper =
+        if (Build.VERSION.SDK_INT < 23) {
+            @Suppress("DEPRECATION") StaticLayout(text, TEXT_PAINT, WIDTH,
+                Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false)
+        } else {
+            StaticLayout.Builder.obtain(text, 0, text.length, TEXT_PAINT, WIDTH).build()
+        }.let {
+            LayoutHelper(it)
+        }
+
+    @Test
+    fun testParagraphInfo() {
+        val layoutHelper = buildLayoutHelper("a\nb\nc")
+        assertThat(layoutHelper.paragraphCount).isEqualTo(3)
+
+        assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(2)
+
+        assertThat(layoutHelper.getParagraphStart(1)).isEqualTo(2)
+        assertThat(layoutHelper.getParagraphEnd(1)).isEqualTo(4)
+
+        assertThat(layoutHelper.getParagraphStart(2)).isEqualTo(4)
+        assertThat(layoutHelper.getParagraphEnd(2)).isEqualTo(5)
+    }
+
+    @Test
+    fun testParagraphInfo_singleParagraph() {
+        val layoutHelper = buildLayoutHelper("Hello, World.")
+        assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+        assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(layoutHelper.layout.text.length)
+    }
+
+    @Test
+    fun testParagraphInfo_ignoreLastLineFeed() {
+        val layoutHelper = buildLayoutHelper("Hello, World.\n")
+        assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+        assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(layoutHelper.layout.text.length)
+    }
+
+    @Test
+    fun testParagraphInfo_emptyText() {
+        val layoutHelper = buildLayoutHelper("")
+        assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+        assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(0)
+    }
+
+    @Test
+    fun testParagraphInfo_lineFeedOnlyCases() {
+        val layoutHelper = buildLayoutHelper("\n")
+        assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+        assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(layoutHelper.layout.text.length)
+    }
+
+    @Test
+    fun testParagraphInfo_lineFeedOnlyCases2() {
+        val layoutHelper = buildLayoutHelper("\n\n")
+        assertThat(layoutHelper.paragraphCount).isEqualTo(2)
+
+        assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(1)
+
+        assertThat(layoutHelper.getParagraphStart(1)).isEqualTo(1)
+        assertThat(layoutHelper.getParagraphEnd(1)).isEqualTo(layoutHelper.layout.text.length)
+    }
+
+    @Test
+    fun testParagraphForOffset() {
+        val layoutHelper = buildLayoutHelper("aa\nbb\ncc")
+        assertThat(layoutHelper.getParagraphForOffset(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphForOffset(1)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphForOffset(2)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphForOffset(3)).isEqualTo(1)
+        assertThat(layoutHelper.getParagraphForOffset(4)).isEqualTo(1)
+        assertThat(layoutHelper.getParagraphForOffset(5)).isEqualTo(1)
+        assertThat(layoutHelper.getParagraphForOffset(6)).isEqualTo(2)
+        assertThat(layoutHelper.getParagraphForOffset(7)).isEqualTo(2)
+    }
+
+    @Test
+    fun testParagraphForOffset_lineFeedOnlyCase() {
+        val layoutHelper = buildLayoutHelper("\n\n")
+        assertThat(layoutHelper.getParagraphForOffset(0)).isEqualTo(0)
+        assertThat(layoutHelper.getParagraphForOffset(1)).isEqualTo(1)
+    }
+
+    @Test
+    fun testParagarphDirection() {
+        val layoutHelper = buildLayoutHelper("aa\nאא\ncc")
+        assertThat(layoutHelper.isRTLParagraph(0)).isFalse()
+        assertThat(layoutHelper.isRTLParagraph(1)).isTrue()
+        assertThat(layoutHelper.isRTLParagraph(2)).isFalse()
+    }
+
+    @Test
+    fun testParagarphDirection_case2() {
+        val layoutHelper = buildLayoutHelper("אא\nbb\nאא")
+        assertThat(layoutHelper.isRTLParagraph(0)).isTrue()
+        assertThat(layoutHelper.isRTLParagraph(1)).isFalse()
+        assertThat(layoutHelper.isRTLParagraph(2)).isTrue()
+    }
+}
\ No newline at end of file
diff --git a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt
index af6d8b2..04dc605 100644
--- a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt
+++ b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt
@@ -19,11 +19,16 @@
 import android.graphics.Paint
 import android.text.TextPaint
 import androidx.ui.text.platform.InternalPlatformTextApi
+import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
 import kotlin.math.abs
 
 @OptIn(InternalPlatformTextApi::class)
+@RunWith(JUnit4::class)
+@SmallTest
 class PlaceholderSpanTest {
     @Test
     fun width_isSp_equalsGiven() {
diff --git a/ui/ui-text-android/src/main/java/androidx/ui/text/platform/LayoutHelper.kt b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/LayoutHelper.kt
new file mode 100644
index 0000000..76cd259
--- /dev/null
+++ b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/LayoutHelper.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.text.Layout
+import androidx.annotation.IntRange
+
+private const val LINE_FEED = '\n'
+
+/**
+ * Provide utilities for Layout class
+ *
+ * @suppress
+ */
+@InternalPlatformTextApi
+class LayoutHelper(val layout: Layout) {
+
+    private val paragraphEnds: List<Int>
+
+    init {
+        var paragraphEnd = 0
+        val lineFeeds = mutableListOf<Int>()
+        do {
+            paragraphEnd = layout.text.indexOf(char = LINE_FEED, startIndex = paragraphEnd)
+            if (paragraphEnd < 0) {
+                // No more LINE_FEED char found. Use the end of the text as the paragraph end.
+                paragraphEnd = layout.text.length
+            } else {
+                // increment since end offset is exclusive.
+                paragraphEnd++
+            }
+            lineFeeds.add(paragraphEnd)
+        } while (paragraphEnd < layout.text.length)
+        paragraphEnds = lineFeeds
+    }
+
+    /**
+     * Retrieve the number of the paragraph in this layout.
+     */
+    val paragraphCount = paragraphEnds.size
+
+    /**
+     * Returns the zero based paragraph number at the offset.
+     *
+     * The paragraphs are divided by line feed character (U+000A) and line feed character is
+     * included in the preceding paragraph, i.e. if the offset points the line feed character,
+     * this function returns preceding paragraph index.
+     *
+     * @param offset a character offset in the text
+     * @return the paragraph number
+     */
+    fun getParagraphForOffset(@IntRange(from = 0) offset: Int): Int =
+        paragraphEnds.binarySearch(offset).let { if (it < 0) - (it + 1) else it + 1 }
+
+    /**
+     * Returns the inclusive paragraph starting offset of the given paragraph index.
+     *
+     * @param paragraphIndex a paragraph index.
+     * @return an inclusive start character offset of the given paragraph.
+     */
+    fun getParagraphStart(@IntRange(from = 0) paragraphIndex: Int) =
+        if (paragraphIndex == 0) 0 else paragraphEnds[paragraphIndex - 1]
+
+    /**
+     * Returns the exclusive paragraph end offset of the given paragraph index.
+     *
+     * @param paragraphIndex a paragraph index.
+     * @return an exclusive end character offset of the given paragraph.
+     */
+    fun getParagraphEnd(@IntRange(from = 0) paragraphIndex: Int) = paragraphEnds[paragraphIndex]
+
+    /**
+     * Returns true if the resolved paragraph direction is RTL, otherwise return false.
+     *
+     * @param paragraphIndex a paragraph index
+     * @return true if the paragraph is RTL, otherwise false
+     */
+    fun isRTLParagraph(@IntRange(from = 0) paragraphIndex: Int): Boolean {
+        val lineNumber = layout.getLineForOffset(getParagraphStart(paragraphIndex))
+        return layout.getParagraphDirection(lineNumber) == Layout.DIR_RIGHT_TO_LEFT
+    }
+}
\ No newline at end of file
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 b84e856..b3f847a 100644
--- a/ui/ui-text-core/api/0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/0.1.0-dev14.txt
@@ -892,14 +892,21 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
+  }
+
   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);
   }
diff --git a/ui/ui-text-core/api/0.1.0-dev15.txt b/ui/ui-text-core/api/0.1.0-dev15.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/0.1.0-dev15.txt
+++ b/ui/ui-text-core/api/0.1.0-dev15.txt
@@ -74,6 +74,8 @@
   }
 
   public enum ImeAction {
+    method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.ImeAction[] values();
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
     enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
   }
 
   public enum KeyboardType {
+    method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.KeyboardType[] values();
     enum_constant public static final androidx.ui.input.KeyboardType Ascii;
     enum_constant public static final androidx.ui.input.KeyboardType Email;
     enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
   public interface OffsetMap {
     method public int originalToTransformed(int offset);
     method public int transformedToOriginal(int offset);
-    field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+    field public static final androidx.ui.input.OffsetMap.Companion Companion;
   }
 
   public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
     method public androidx.ui.text.TextRange? getComposition();
     method public androidx.ui.text.TextRange getSelection();
     method public String getText();
-    field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+    field public static final androidx.ui.input.TextFieldValue.Companion Companion;
   }
 
   public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
 
   @androidx.compose.Immutable public interface VisualTransformation {
     method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
-    field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+    field public static final androidx.ui.input.VisualTransformation.Companion Companion;
   }
 
   public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
     property public final String language;
     property public final String region;
     property public final String script;
-    field public static final androidx.ui.intl.Locale.Companion! Companion;
+    field public static final androidx.ui.intl.Locale.Companion Companion;
   }
 
   public static final class Locale.Companion {
@@ -265,7 +269,7 @@
     method public boolean isEmpty();
     method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
     property public int size;
-    field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+    field public static final androidx.ui.intl.LocaleList.Companion Companion;
   }
 
   public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
   }
 
   public enum PlaceholderVerticalAlign {
+    method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
 
   public final class TextPainter {
     method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    field public static final androidx.ui.text.TextPainter! INSTANCE;
+    field public static final androidx.ui.text.TextPainter INSTANCE;
   }
 
   @androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
     method public int getLength();
     method public int getMax();
     method public int getMin();
+    method public boolean getReversed();
     method public int getStart();
     method public boolean intersects(androidx.ui.text.TextRange other);
     property public final boolean collapsed;
     property public final int length;
     property public final int max;
     property public final int min;
-    field public static final androidx.ui.text.TextRange.Companion! Companion;
+    property public final boolean reversed;
+    field public static final androidx.ui.text.TextRange.Companion Companion;
   }
 
   public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
     method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
     method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
-    field public static final androidx.ui.text.TextStyle.Companion! Companion;
+    field public static final androidx.ui.text.TextStyle.Companion Companion;
   }
 
   public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
 
   @androidx.compose.Immutable public abstract sealed class FontFamily {
     method public final boolean getCanLoadSynchronously();
-    field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+    field public static final androidx.ui.text.font.FontFamily.Companion Companion;
   }
 
   public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
   }
 
   public enum FontStyle {
+    method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontStyle[] values();
     enum_constant public static final androidx.ui.text.font.FontStyle Italic;
     enum_constant public static final androidx.ui.text.font.FontStyle Normal;
   }
 
   public enum FontSynthesis {
+    method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontSynthesis[] values();
     enum_constant public static final androidx.ui.text.font.FontSynthesis All;
     enum_constant public static final androidx.ui.text.font.FontSynthesis None;
     enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
     method public int component1();
     method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
     method public int getWeight();
-    field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+    field public static final androidx.ui.text.font.FontWeight.Companion Companion;
   }
 
   public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
     method public float getMultiplier();
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Immutable public static inline String! toString-impl(float p);
-    field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+    field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
   }
 
   public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
   }
 
   public enum TextAlign {
+    method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextAlign[] values();
     enum_constant public static final androidx.ui.text.style.TextAlign Center;
     enum_constant public static final androidx.ui.text.style.TextAlign End;
     enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
     method public boolean contains(androidx.ui.text.style.TextDecoration other);
     method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
     method public int getMask();
-    field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+    field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
   }
 
   public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
   }
 
   public enum TextDirection {
+    method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirection[] values();
     enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
     enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
   }
 
   public enum TextDirectionAlgorithm {
+    method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
     method public float getScaleX();
     method public float getSkewX();
-    field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+    field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
   }
 
   public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
     method public long getFirstLine();
     method public long getRestLine();
-    field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+    field public static final androidx.ui.text.style.TextIndent.Companion Companion;
   }
 
   public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
   }
 
   public enum TextOverflow {
+    method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextOverflow[] values();
     enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
     enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
   }
diff --git a/ui/ui-text-core/api/current.txt b/ui/ui-text-core/api/current.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/current.txt
+++ b/ui/ui-text-core/api/current.txt
@@ -74,6 +74,8 @@
   }
 
   public enum ImeAction {
+    method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.ImeAction[] values();
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
     enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
   }
 
   public enum KeyboardType {
+    method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.KeyboardType[] values();
     enum_constant public static final androidx.ui.input.KeyboardType Ascii;
     enum_constant public static final androidx.ui.input.KeyboardType Email;
     enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
   public interface OffsetMap {
     method public int originalToTransformed(int offset);
     method public int transformedToOriginal(int offset);
-    field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+    field public static final androidx.ui.input.OffsetMap.Companion Companion;
   }
 
   public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
     method public androidx.ui.text.TextRange? getComposition();
     method public androidx.ui.text.TextRange getSelection();
     method public String getText();
-    field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+    field public static final androidx.ui.input.TextFieldValue.Companion Companion;
   }
 
   public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
 
   @androidx.compose.Immutable public interface VisualTransformation {
     method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
-    field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+    field public static final androidx.ui.input.VisualTransformation.Companion Companion;
   }
 
   public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
     property public final String language;
     property public final String region;
     property public final String script;
-    field public static final androidx.ui.intl.Locale.Companion! Companion;
+    field public static final androidx.ui.intl.Locale.Companion Companion;
   }
 
   public static final class Locale.Companion {
@@ -265,7 +269,7 @@
     method public boolean isEmpty();
     method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
     property public int size;
-    field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+    field public static final androidx.ui.intl.LocaleList.Companion Companion;
   }
 
   public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
   }
 
   public enum PlaceholderVerticalAlign {
+    method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
 
   public final class TextPainter {
     method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    field public static final androidx.ui.text.TextPainter! INSTANCE;
+    field public static final androidx.ui.text.TextPainter INSTANCE;
   }
 
   @androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
     method public int getLength();
     method public int getMax();
     method public int getMin();
+    method public boolean getReversed();
     method public int getStart();
     method public boolean intersects(androidx.ui.text.TextRange other);
     property public final boolean collapsed;
     property public final int length;
     property public final int max;
     property public final int min;
-    field public static final androidx.ui.text.TextRange.Companion! Companion;
+    property public final boolean reversed;
+    field public static final androidx.ui.text.TextRange.Companion Companion;
   }
 
   public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
     method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
     method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
-    field public static final androidx.ui.text.TextStyle.Companion! Companion;
+    field public static final androidx.ui.text.TextStyle.Companion Companion;
   }
 
   public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
 
   @androidx.compose.Immutable public abstract sealed class FontFamily {
     method public final boolean getCanLoadSynchronously();
-    field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+    field public static final androidx.ui.text.font.FontFamily.Companion Companion;
   }
 
   public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
   }
 
   public enum FontStyle {
+    method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontStyle[] values();
     enum_constant public static final androidx.ui.text.font.FontStyle Italic;
     enum_constant public static final androidx.ui.text.font.FontStyle Normal;
   }
 
   public enum FontSynthesis {
+    method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontSynthesis[] values();
     enum_constant public static final androidx.ui.text.font.FontSynthesis All;
     enum_constant public static final androidx.ui.text.font.FontSynthesis None;
     enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
     method public int component1();
     method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
     method public int getWeight();
-    field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+    field public static final androidx.ui.text.font.FontWeight.Companion Companion;
   }
 
   public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
     method public float getMultiplier();
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Immutable public static inline String! toString-impl(float p);
-    field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+    field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
   }
 
   public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
   }
 
   public enum TextAlign {
+    method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextAlign[] values();
     enum_constant public static final androidx.ui.text.style.TextAlign Center;
     enum_constant public static final androidx.ui.text.style.TextAlign End;
     enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
     method public boolean contains(androidx.ui.text.style.TextDecoration other);
     method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
     method public int getMask();
-    field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+    field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
   }
 
   public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
   }
 
   public enum TextDirection {
+    method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirection[] values();
     enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
     enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
   }
 
   public enum TextDirectionAlgorithm {
+    method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
     method public float getScaleX();
     method public float getSkewX();
-    field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+    field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
   }
 
   public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
     method public long getFirstLine();
     method public long getRestLine();
-    field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+    field public static final androidx.ui.text.style.TextIndent.Companion Companion;
   }
 
   public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
   }
 
   public enum TextOverflow {
+    method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextOverflow[] values();
     enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
     enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
   }
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 b84e856..b3f847a 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
@@ -892,14 +892,21 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
+  }
+
   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);
   }
diff --git a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -74,6 +74,8 @@
   }
 
   public enum ImeAction {
+    method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.ImeAction[] values();
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
     enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
   }
 
   public enum KeyboardType {
+    method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.KeyboardType[] values();
     enum_constant public static final androidx.ui.input.KeyboardType Ascii;
     enum_constant public static final androidx.ui.input.KeyboardType Email;
     enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
   public interface OffsetMap {
     method public int originalToTransformed(int offset);
     method public int transformedToOriginal(int offset);
-    field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+    field public static final androidx.ui.input.OffsetMap.Companion Companion;
   }
 
   public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
     method public androidx.ui.text.TextRange? getComposition();
     method public androidx.ui.text.TextRange getSelection();
     method public String getText();
-    field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+    field public static final androidx.ui.input.TextFieldValue.Companion Companion;
   }
 
   public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
 
   @androidx.compose.Immutable public interface VisualTransformation {
     method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
-    field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+    field public static final androidx.ui.input.VisualTransformation.Companion Companion;
   }
 
   public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
     property public final String language;
     property public final String region;
     property public final String script;
-    field public static final androidx.ui.intl.Locale.Companion! Companion;
+    field public static final androidx.ui.intl.Locale.Companion Companion;
   }
 
   public static final class Locale.Companion {
@@ -265,7 +269,7 @@
     method public boolean isEmpty();
     method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
     property public int size;
-    field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+    field public static final androidx.ui.intl.LocaleList.Companion Companion;
   }
 
   public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
   }
 
   public enum PlaceholderVerticalAlign {
+    method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
 
   public final class TextPainter {
     method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    field public static final androidx.ui.text.TextPainter! INSTANCE;
+    field public static final androidx.ui.text.TextPainter INSTANCE;
   }
 
   @androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
     method public int getLength();
     method public int getMax();
     method public int getMin();
+    method public boolean getReversed();
     method public int getStart();
     method public boolean intersects(androidx.ui.text.TextRange other);
     property public final boolean collapsed;
     property public final int length;
     property public final int max;
     property public final int min;
-    field public static final androidx.ui.text.TextRange.Companion! Companion;
+    property public final boolean reversed;
+    field public static final androidx.ui.text.TextRange.Companion Companion;
   }
 
   public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
     method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
     method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
-    field public static final androidx.ui.text.TextStyle.Companion! Companion;
+    field public static final androidx.ui.text.TextStyle.Companion Companion;
   }
 
   public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
 
   @androidx.compose.Immutable public abstract sealed class FontFamily {
     method public final boolean getCanLoadSynchronously();
-    field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+    field public static final androidx.ui.text.font.FontFamily.Companion Companion;
   }
 
   public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
   }
 
   public enum FontStyle {
+    method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontStyle[] values();
     enum_constant public static final androidx.ui.text.font.FontStyle Italic;
     enum_constant public static final androidx.ui.text.font.FontStyle Normal;
   }
 
   public enum FontSynthesis {
+    method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontSynthesis[] values();
     enum_constant public static final androidx.ui.text.font.FontSynthesis All;
     enum_constant public static final androidx.ui.text.font.FontSynthesis None;
     enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
     method public int component1();
     method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
     method public int getWeight();
-    field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+    field public static final androidx.ui.text.font.FontWeight.Companion Companion;
   }
 
   public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
     method public float getMultiplier();
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Immutable public static inline String! toString-impl(float p);
-    field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+    field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
   }
 
   public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
   }
 
   public enum TextAlign {
+    method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextAlign[] values();
     enum_constant public static final androidx.ui.text.style.TextAlign Center;
     enum_constant public static final androidx.ui.text.style.TextAlign End;
     enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
     method public boolean contains(androidx.ui.text.style.TextDecoration other);
     method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
     method public int getMask();
-    field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+    field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
   }
 
   public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
   }
 
   public enum TextDirection {
+    method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirection[] values();
     enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
     enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
   }
 
   public enum TextDirectionAlgorithm {
+    method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
     method public float getScaleX();
     method public float getSkewX();
-    field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+    field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
   }
 
   public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
     method public long getFirstLine();
     method public long getRestLine();
-    field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+    field public static final androidx.ui.text.style.TextIndent.Companion Companion;
   }
 
   public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
   }
 
   public enum TextOverflow {
+    method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextOverflow[] values();
     enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
     enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
   }
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 b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_current.txt
@@ -74,6 +74,8 @@
   }
 
   public enum ImeAction {
+    method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.ImeAction[] values();
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
     enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
   }
 
   public enum KeyboardType {
+    method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.KeyboardType[] values();
     enum_constant public static final androidx.ui.input.KeyboardType Ascii;
     enum_constant public static final androidx.ui.input.KeyboardType Email;
     enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
   public interface OffsetMap {
     method public int originalToTransformed(int offset);
     method public int transformedToOriginal(int offset);
-    field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+    field public static final androidx.ui.input.OffsetMap.Companion Companion;
   }
 
   public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
     method public androidx.ui.text.TextRange? getComposition();
     method public androidx.ui.text.TextRange getSelection();
     method public String getText();
-    field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+    field public static final androidx.ui.input.TextFieldValue.Companion Companion;
   }
 
   public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
 
   @androidx.compose.Immutable public interface VisualTransformation {
     method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
-    field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+    field public static final androidx.ui.input.VisualTransformation.Companion Companion;
   }
 
   public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
     property public final String language;
     property public final String region;
     property public final String script;
-    field public static final androidx.ui.intl.Locale.Companion! Companion;
+    field public static final androidx.ui.intl.Locale.Companion Companion;
   }
 
   public static final class Locale.Companion {
@@ -265,7 +269,7 @@
     method public boolean isEmpty();
     method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
     property public int size;
-    field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+    field public static final androidx.ui.intl.LocaleList.Companion Companion;
   }
 
   public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
   }
 
   public enum PlaceholderVerticalAlign {
+    method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
 
   public final class TextPainter {
     method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    field public static final androidx.ui.text.TextPainter! INSTANCE;
+    field public static final androidx.ui.text.TextPainter INSTANCE;
   }
 
   @androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
     method public int getLength();
     method public int getMax();
     method public int getMin();
+    method public boolean getReversed();
     method public int getStart();
     method public boolean intersects(androidx.ui.text.TextRange other);
     property public final boolean collapsed;
     property public final int length;
     property public final int max;
     property public final int min;
-    field public static final androidx.ui.text.TextRange.Companion! Companion;
+    property public final boolean reversed;
+    field public static final androidx.ui.text.TextRange.Companion Companion;
   }
 
   public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
     method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
     method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
-    field public static final androidx.ui.text.TextStyle.Companion! Companion;
+    field public static final androidx.ui.text.TextStyle.Companion Companion;
   }
 
   public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
 
   @androidx.compose.Immutable public abstract sealed class FontFamily {
     method public final boolean getCanLoadSynchronously();
-    field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+    field public static final androidx.ui.text.font.FontFamily.Companion Companion;
   }
 
   public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
   }
 
   public enum FontStyle {
+    method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontStyle[] values();
     enum_constant public static final androidx.ui.text.font.FontStyle Italic;
     enum_constant public static final androidx.ui.text.font.FontStyle Normal;
   }
 
   public enum FontSynthesis {
+    method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontSynthesis[] values();
     enum_constant public static final androidx.ui.text.font.FontSynthesis All;
     enum_constant public static final androidx.ui.text.font.FontSynthesis None;
     enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
     method public int component1();
     method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
     method public int getWeight();
-    field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+    field public static final androidx.ui.text.font.FontWeight.Companion Companion;
   }
 
   public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
     method public float getMultiplier();
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Immutable public static inline String! toString-impl(float p);
-    field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+    field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
   }
 
   public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
   }
 
   public enum TextAlign {
+    method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextAlign[] values();
     enum_constant public static final androidx.ui.text.style.TextAlign Center;
     enum_constant public static final androidx.ui.text.style.TextAlign End;
     enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
     method public boolean contains(androidx.ui.text.style.TextDecoration other);
     method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
     method public int getMask();
-    field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+    field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
   }
 
   public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
   }
 
   public enum TextDirection {
+    method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirection[] values();
     enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
     enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
   }
 
   public enum TextDirectionAlgorithm {
+    method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
     method public float getScaleX();
     method public float getSkewX();
-    field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+    field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
   }
 
   public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
     method public long getFirstLine();
     method public long getRestLine();
-    field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+    field public static final androidx.ui.text.style.TextIndent.Companion Companion;
   }
 
   public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
   }
 
   public enum TextOverflow {
+    method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextOverflow[] values();
     enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
     enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
   }
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 b84e856..b3f847a 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
@@ -892,14 +892,21 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
   }
 
+  @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
+  }
+
   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);
   }
diff --git a/ui/ui-text-core/api/restricted_0.1.0-dev15.txt b/ui/ui-text-core/api/restricted_0.1.0-dev15.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-text-core/api/restricted_0.1.0-dev15.txt
@@ -74,6 +74,8 @@
   }
 
   public enum ImeAction {
+    method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.ImeAction[] values();
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
     enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
   }
 
   public enum KeyboardType {
+    method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.KeyboardType[] values();
     enum_constant public static final androidx.ui.input.KeyboardType Ascii;
     enum_constant public static final androidx.ui.input.KeyboardType Email;
     enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
   public interface OffsetMap {
     method public int originalToTransformed(int offset);
     method public int transformedToOriginal(int offset);
-    field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+    field public static final androidx.ui.input.OffsetMap.Companion Companion;
   }
 
   public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
     method public androidx.ui.text.TextRange? getComposition();
     method public androidx.ui.text.TextRange getSelection();
     method public String getText();
-    field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+    field public static final androidx.ui.input.TextFieldValue.Companion Companion;
   }
 
   public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
 
   @androidx.compose.Immutable public interface VisualTransformation {
     method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
-    field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+    field public static final androidx.ui.input.VisualTransformation.Companion Companion;
   }
 
   public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
     property public final String language;
     property public final String region;
     property public final String script;
-    field public static final androidx.ui.intl.Locale.Companion! Companion;
+    field public static final androidx.ui.intl.Locale.Companion Companion;
   }
 
   public static final class Locale.Companion {
@@ -265,7 +269,7 @@
     method public boolean isEmpty();
     method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
     property public int size;
-    field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+    field public static final androidx.ui.intl.LocaleList.Companion Companion;
   }
 
   public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
   }
 
   public enum PlaceholderVerticalAlign {
+    method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
 
   public final class TextPainter {
     method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    field public static final androidx.ui.text.TextPainter! INSTANCE;
+    field public static final androidx.ui.text.TextPainter INSTANCE;
   }
 
   @androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
     method public int getLength();
     method public int getMax();
     method public int getMin();
+    method public boolean getReversed();
     method public int getStart();
     method public boolean intersects(androidx.ui.text.TextRange other);
     property public final boolean collapsed;
     property public final int length;
     property public final int max;
     property public final int min;
-    field public static final androidx.ui.text.TextRange.Companion! Companion;
+    property public final boolean reversed;
+    field public static final androidx.ui.text.TextRange.Companion Companion;
   }
 
   public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
     method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
     method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
-    field public static final androidx.ui.text.TextStyle.Companion! Companion;
+    field public static final androidx.ui.text.TextStyle.Companion Companion;
   }
 
   public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
 
   @androidx.compose.Immutable public abstract sealed class FontFamily {
     method public final boolean getCanLoadSynchronously();
-    field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+    field public static final androidx.ui.text.font.FontFamily.Companion Companion;
   }
 
   public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
   }
 
   public enum FontStyle {
+    method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontStyle[] values();
     enum_constant public static final androidx.ui.text.font.FontStyle Italic;
     enum_constant public static final androidx.ui.text.font.FontStyle Normal;
   }
 
   public enum FontSynthesis {
+    method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontSynthesis[] values();
     enum_constant public static final androidx.ui.text.font.FontSynthesis All;
     enum_constant public static final androidx.ui.text.font.FontSynthesis None;
     enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
     method public int component1();
     method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
     method public int getWeight();
-    field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+    field public static final androidx.ui.text.font.FontWeight.Companion Companion;
   }
 
   public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
     method public float getMultiplier();
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Immutable public static inline String! toString-impl(float p);
-    field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+    field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
   }
 
   public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
   }
 
   public enum TextAlign {
+    method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextAlign[] values();
     enum_constant public static final androidx.ui.text.style.TextAlign Center;
     enum_constant public static final androidx.ui.text.style.TextAlign End;
     enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
     method public boolean contains(androidx.ui.text.style.TextDecoration other);
     method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
     method public int getMask();
-    field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+    field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
   }
 
   public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
   }
 
   public enum TextDirection {
+    method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirection[] values();
     enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
     enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
   }
 
   public enum TextDirectionAlgorithm {
+    method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
     method public float getScaleX();
     method public float getSkewX();
-    field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+    field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
   }
 
   public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
     method public long getFirstLine();
     method public long getRestLine();
-    field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+    field public static final androidx.ui.text.style.TextIndent.Companion Companion;
   }
 
   public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
   }
 
   public enum TextOverflow {
+    method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextOverflow[] values();
     enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
     enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
   }
diff --git a/ui/ui-text-core/api/restricted_current.txt b/ui/ui-text-core/api/restricted_current.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/restricted_current.txt
+++ b/ui/ui-text-core/api/restricted_current.txt
@@ -74,6 +74,8 @@
   }
 
   public enum ImeAction {
+    method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.ImeAction[] values();
     enum_constant public static final androidx.ui.input.ImeAction Done;
     enum_constant public static final androidx.ui.input.ImeAction Go;
     enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
   }
 
   public enum KeyboardType {
+    method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.input.KeyboardType[] values();
     enum_constant public static final androidx.ui.input.KeyboardType Ascii;
     enum_constant public static final androidx.ui.input.KeyboardType Email;
     enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
   public interface OffsetMap {
     method public int originalToTransformed(int offset);
     method public int transformedToOriginal(int offset);
-    field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+    field public static final androidx.ui.input.OffsetMap.Companion Companion;
   }
 
   public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
     method public androidx.ui.text.TextRange? getComposition();
     method public androidx.ui.text.TextRange getSelection();
     method public String getText();
-    field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+    field public static final androidx.ui.input.TextFieldValue.Companion Companion;
   }
 
   public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
 
   @androidx.compose.Immutable public interface VisualTransformation {
     method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
-    field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+    field public static final androidx.ui.input.VisualTransformation.Companion Companion;
   }
 
   public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
     property public final String language;
     property public final String region;
     property public final String script;
-    field public static final androidx.ui.intl.Locale.Companion! Companion;
+    field public static final androidx.ui.intl.Locale.Companion Companion;
   }
 
   public static final class Locale.Companion {
@@ -265,7 +269,7 @@
     method public boolean isEmpty();
     method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
     property public int size;
-    field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+    field public static final androidx.ui.intl.LocaleList.Companion Companion;
   }
 
   public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
   }
 
   public enum PlaceholderVerticalAlign {
+    method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
     enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
 
   public final class TextPainter {
     method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
-    field public static final androidx.ui.text.TextPainter! INSTANCE;
+    field public static final androidx.ui.text.TextPainter INSTANCE;
   }
 
   @androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
     method public int getLength();
     method public int getMax();
     method public int getMin();
+    method public boolean getReversed();
     method public int getStart();
     method public boolean intersects(androidx.ui.text.TextRange other);
     property public final boolean collapsed;
     property public final int length;
     property public final int max;
     property public final int min;
-    field public static final androidx.ui.text.TextRange.Companion! Companion;
+    property public final boolean reversed;
+    field public static final androidx.ui.text.TextRange.Companion Companion;
   }
 
   public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
     method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
     method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
     method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
-    field public static final androidx.ui.text.TextStyle.Companion! Companion;
+    field public static final androidx.ui.text.TextStyle.Companion Companion;
   }
 
   public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
 
   @androidx.compose.Immutable public abstract sealed class FontFamily {
     method public final boolean getCanLoadSynchronously();
-    field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+    field public static final androidx.ui.text.font.FontFamily.Companion Companion;
   }
 
   public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
   }
 
   public enum FontStyle {
+    method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontStyle[] values();
     enum_constant public static final androidx.ui.text.font.FontStyle Italic;
     enum_constant public static final androidx.ui.text.font.FontStyle Normal;
   }
 
   public enum FontSynthesis {
+    method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.font.FontSynthesis[] values();
     enum_constant public static final androidx.ui.text.font.FontSynthesis All;
     enum_constant public static final androidx.ui.text.font.FontSynthesis None;
     enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
     method public int component1();
     method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
     method public int getWeight();
-    field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+    field public static final androidx.ui.text.font.FontWeight.Companion Companion;
   }
 
   public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
   }
 
   public final class AndroidParagraphIntrinsicsKt {
+    method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+    method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
   }
 
   public final class AndroidParagraphKt {
+    method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+    method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
   }
 
   public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
     method public float getMultiplier();
     method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
     method @androidx.compose.Immutable public static inline String! toString-impl(float p);
-    field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+    field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
   }
 
   public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
   }
 
   public enum TextAlign {
+    method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextAlign[] values();
     enum_constant public static final androidx.ui.text.style.TextAlign Center;
     enum_constant public static final androidx.ui.text.style.TextAlign End;
     enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
     method public boolean contains(androidx.ui.text.style.TextDecoration other);
     method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
     method public int getMask();
-    field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+    field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
   }
 
   public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
   }
 
   public enum TextDirection {
+    method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirection[] values();
     enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
     enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
   }
 
   public enum TextDirectionAlgorithm {
+    method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
     enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
     method public float getScaleX();
     method public float getSkewX();
-    field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+    field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
   }
 
   public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
     method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
     method public long getFirstLine();
     method public long getRestLine();
-    field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+    field public static final androidx.ui.text.style.TextIndent.Companion Companion;
   }
 
   public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
   }
 
   public enum TextOverflow {
+    method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.text.style.TextOverflow[] values();
     enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
     enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
   }
diff --git a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
index 6c9ac37..b79162c 100644
--- a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
@@ -338,6 +338,26 @@
     else -> DEFAULT_ALIGNMENT
 }
 
+// TODO(b/159152328): temporary workaround for ui-desktop. remove when full support of MPP will be in-place
+@Deprecated(
+    "Temporary workaround. Supposed to be used only in ui-desktop before MPP",
+    level = DeprecationLevel.ERROR
+)
+@InternalPlatformTextApi
+var paragraphActualFactory: ((
+    paragraphIntrinsics: ParagraphIntrinsics,
+    maxLines: Int,
+    ellipsis: Boolean,
+    constraints: ParagraphConstraints
+) -> Paragraph) = { paragraphIntrinsics, maxLines, ellipsis, constraints ->
+    AndroidParagraph(
+        paragraphIntrinsics as AndroidParagraphIntrinsics,
+        maxLines,
+        ellipsis,
+        constraints)
+}
+
+@OptIn(InternalPlatformTextApi::class)
 internal actual fun ActualParagraph(
     text: String,
     style: TextStyle,
@@ -348,32 +368,32 @@
     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
+): Paragraph =
+    @Suppress("DEPRECATION_ERROR")
+    paragraphActualFactory(
+        ActualParagraphIntrinsics(
+            text,
+            style,
+            spanStyles,
+            placeholders,
+            density,
+            resourceLoader
         ),
-        density = density
+        maxLines,
+        ellipsis,
+        constraints
     )
-}
 
+@OptIn(InternalPlatformTextApi::class)
 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
+): Paragraph =
+    @Suppress("DEPRECATION_ERROR")
+    paragraphActualFactory(
+        paragraphIntrinsics,
+        maxLines,
+        ellipsis,
+    constraints)
diff --git a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
index 64a7174..97cdc1d 100644
--- a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
@@ -82,14 +82,21 @@
     }
 }
 
-internal actual fun ActualParagraphIntrinsics(
+// TODO(b/159152328): temporary workaround for ui-desktop. remove when full support of MPP will be in-place
+@Deprecated(
+    "Temporary workaround. Supposed to be used only in ui-desktop before MPP",
+    level = DeprecationLevel.ERROR
+)
+@InternalPlatformTextApi
+var paragraphIntrinsicsActualFactory: ((
     text: String,
     style: TextStyle,
     spanStyles: List<AnnotatedString.Range<SpanStyle>>,
     placeholders: List<AnnotatedString.Range<Placeholder>>,
     density: Density,
     resourceLoader: Font.ResourceLoader
-): ParagraphIntrinsics = AndroidParagraphIntrinsics(
+) -> ParagraphIntrinsics) = { text, style, spanStyles, placeholders, density, resourceLoader ->
+    AndroidParagraphIntrinsics(
         text = text,
         style = style,
         placeholders = placeholders,
@@ -98,4 +105,19 @@
         ),
         spanStyles = spanStyles,
         density = density
+    )
+}
+
+@OptIn(InternalPlatformTextApi::class)
+internal actual fun ActualParagraphIntrinsics(
+    text: String,
+    style: TextStyle,
+    spanStyles: List<AnnotatedString.Range<SpanStyle>>,
+    placeholders: List<AnnotatedString.Range<Placeholder>>,
+    density: Density,
+    resourceLoader: Font.ResourceLoader
+): ParagraphIntrinsics =
+    @Suppress("DEPRECATION_ERROR")
+    paragraphIntrinsicsActualFactory(
+        text, style, spanStyles, placeholders, density, resourceLoader
     )
\ No newline at end of file
diff --git a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
index 39479b2..ecb624c 100644
--- a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
@@ -45,6 +45,11 @@
     val collapsed: Boolean get() = start == end
 
     /**
+     * Returns true if the start offset is larger than the end offset.
+     */
+    val reversed: Boolean get() = start > end
+
+    /**
      * Returns the length of the range.
      */
     val length: Int get() = max - min
@@ -82,3 +87,24 @@
  * Creates a [TextRange] where start is equal to end, and the value of those are [index].
  */
 fun TextRange(index: Int): TextRange = TextRange(start = index, end = index)
+
+/**
+ * Ensures that [TextRange.start] and [TextRange.end] values lies in the specified range
+ * [minimumValue] and [maximumValue]. For each [TextRange.start] and [TextRange.end] values:
+ * - if value is smaller than [minimumValue], value is replaced by [minimumValue]
+ * - if value is greater than [maximumValue], value is replaced by [maximumValue]
+ *
+ * @param minimumValue the minimum value that [TextRange.start] or [TextRange.end] can be.
+ * @param maximumValue the exclusive maximum value that [TextRange.start] or [TextRange.end] can be.
+ *
+ * @suppress
+ */
+@InternalTextApi
+fun TextRange.constrain(minimumValue: Int, maximumValue: Int): TextRange {
+    val newStart = start.coerceIn(minimumValue, maximumValue)
+    val newEnd = end.coerceIn(minimumValue, maximumValue)
+    if (newStart != start || newEnd != end) {
+        return TextRange(newStart, newEnd)
+    }
+    return this
+}
\ No newline at end of file
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
index c74f11b..92761f5 100644
--- 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
@@ -54,4 +54,4 @@
     placeholders: List<AnnotatedString.Range<Placeholder>>,
     density: Density,
     resourceLoader: Font.ResourceLoader
-): ParagraphIntrinsics
+): ParagraphIntrinsics
\ No newline at end of file
diff --git a/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt b/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt
index 47b3f90..cb4d375 100644
--- a/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt
+++ b/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt
@@ -21,6 +21,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
+@OptIn(InternalTextApi::class)
 @RunWith(JUnit4::class)
 class TextRangeTest {
     @Test
@@ -60,6 +61,15 @@
     }
 
     @Test
+    fun test_range_reversed() {
+        assertThat(TextRange(0, 0).reversed).isFalse()
+        assertThat(TextRange(0, 1).reversed).isFalse()
+
+        assertThat(TextRange(1, 0).reversed).isTrue()
+        assertThat(TextRange(3, 2).reversed).isTrue()
+    }
+
+    @Test
     fun test_intersects() {
         // same values intersect
         assertThat(TextRange(0, 1).intersects(TextRange(0, 1))).isTrue()
@@ -127,4 +137,37 @@
     fun test_does_not_accept_negative_value_for_end() {
         TextRange(1, -1)
     }
+
+    @Test
+    fun constrain_returns_same_object_if_no_change_required() {
+        val textRange = TextRange(1, 2)
+        assertThat(textRange.constrain(0, 3)).isSameInstanceAs(textRange)
+    }
+
+    @Test
+    fun constrain_updates_start_end_if_required() {
+        assertThat(TextRange(0, 4).constrain(1, 3)).isEqualTo(TextRange(1, 3))
+    }
+
+    @Test
+    fun constrain_collapsed_TextRange_with_the_same_min_max_returns_the_same_instance() {
+        val textRange = TextRange(2, 2)
+        assertThat(textRange.constrain(2, 2)).isSameInstanceAs(textRange)
+    }
+
+    @Test
+    fun constrain_with_collapsed_min_max_returns_collapsed_values() {
+        assertThat(TextRange(1, 2).constrain(2, 2)).isEqualTo(TextRange(2, 2))
+        assertThat(TextRange(2, 3).constrain(2, 2)).isEqualTo(TextRange(2, 2))
+    }
+
+    @Test
+    fun constrain_min_max_greater_than_TextRange_values() {
+        assertThat(TextRange(0, 4).constrain(5, 6)).isEqualTo(TextRange(5, 5))
+    }
+
+    @Test
+    fun constrain_min_smaller_than_TextRange_values() {
+        assertThat(TextRange(5, 6).constrain(0, 4)).isEqualTo(TextRange(4, 4))
+    }
 }
\ No newline at end of file
diff --git a/ui/ui-text/api/0.1.0-dev15.txt b/ui/ui-text/api/0.1.0-dev15.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/0.1.0-dev15.txt
+++ b/ui/ui-text/api/0.1.0-dev15.txt
@@ -33,7 +33,7 @@
     method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
-    field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
   }
 
   public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
 
 package androidx.ui.text.selection {
 
+  public final class MultiWidgetSelectionDelegateKt {
+  }
+
+  public final class TextFieldSelectionDelegateKt {
+  }
+
   public final class TextSelectionDelegateKt {
   }
 
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -33,7 +33,7 @@
     method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
-    field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
   }
 
   public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
 
 package androidx.ui.text.selection {
 
+  public final class MultiWidgetSelectionDelegateKt {
+  }
+
+  public final class TextFieldSelectionDelegateKt {
+  }
+
   public final class TextSelectionDelegateKt {
   }
 
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
@@ -33,7 +33,7 @@
     method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
-    field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
   }
 
   public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
 
 package androidx.ui.text.selection {
 
+  public final class MultiWidgetSelectionDelegateKt {
+  }
+
+  public final class TextFieldSelectionDelegateKt {
+  }
+
   public final class TextSelectionDelegateKt {
   }
 
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -33,7 +33,7 @@
     method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
-    field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
   }
 
   public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
 
 package androidx.ui.text.selection {
 
+  public final class MultiWidgetSelectionDelegateKt {
+  }
+
+  public final class TextFieldSelectionDelegateKt {
+  }
+
   public final class TextSelectionDelegateKt {
   }
 
diff --git a/ui/ui-text/api/restricted_0.1.0-dev15.txt b/ui/ui-text/api/restricted_0.1.0-dev15.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev15.txt
@@ -33,7 +33,7 @@
     method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
-    field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
   }
 
   public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
 
 package androidx.ui.text.selection {
 
+  public final class MultiWidgetSelectionDelegateKt {
+  }
+
+  public final class TextFieldSelectionDelegateKt {
+  }
+
   public final class TextSelectionDelegateKt {
   }
 
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -33,7 +33,7 @@
     method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
     property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
     property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
-    field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+    field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
   }
 
   public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
 
 package androidx.ui.text.selection {
 
+  public final class MultiWidgetSelectionDelegateKt {
+  }
+
+  public final class TextFieldSelectionDelegateKt {
+  }
+
   public final class TextSelectionDelegateKt {
   }
 
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/MultiWidgetSelectionDelegateTest.kt
similarity index 96%
rename from ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt
rename to ui/ui-text/src/androidTest/java/androidx/ui/text/selection/MultiWidgetSelectionDelegateTest.kt
index 280605b..97738f1 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/MultiWidgetSelectionDelegateTest.kt
@@ -63,7 +63,7 @@
 @OptIn(InternalTextApi::class)
 @RunWith(JUnit4::class)
 @SmallTest
-class TextSelectionDelegateTest {
+class MultiWidgetSelectionDelegateTest {
     @get:Rule
     val composeTestRule = AndroidComposeTestRule<ComponentActivity>()
 
@@ -88,13 +88,13 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
                 )
 
-                val selectableInvalid = TextSelectionDelegate(
+                val selectableInvalid = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { null },
                     layoutResultCallback = { layoutResult }
@@ -145,13 +145,13 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
                 )
 
-                val selectableInvalid = TextSelectionDelegate(
+                val selectableInvalid = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { null },
                     layoutResultCallback = { layoutResult }
@@ -203,7 +203,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -257,7 +257,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -311,7 +311,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -365,7 +365,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -421,7 +421,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -477,7 +477,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -531,7 +531,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -585,7 +585,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -639,7 +639,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -693,7 +693,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -749,7 +749,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -805,7 +805,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -851,7 +851,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -881,7 +881,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = {},
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -909,7 +909,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = mock(),
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -946,7 +946,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = mock(),
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -981,7 +981,7 @@
                 val layoutCoordinates = mock<LayoutCoordinates>()
                 whenever(layoutCoordinates.isAttached).thenReturn(true)
 
-                val selectable = TextSelectionDelegate(
+                val selectable = MultiWidgetSelectionDelegate(
                     selectionRangeUpdate = mock(),
                     coordinatesCallback = { layoutCoordinates },
                     layoutResultCallback = { layoutResult }
@@ -1310,7 +1310,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_single_widget_handles_crossed_ltr() {
+    fun getTextSelectionInfo_single_widget_handles_crossed_ltr() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1351,7 +1351,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_single_widget_handles_crossed_rtl() {
+    fun getTextSelectionInfo_single_widget_handles_crossed_rtl() {
         with(defaultDensity) {
             val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
             val fontSize = 20.sp
@@ -1399,7 +1399,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_single_widget_handles_crossed_bidi() {
+    fun getTextSelectionInfo_single_widget_handles_crossed_bidi() {
         with(defaultDensity) {
             val textLtr = "Hello"
             val textRtl = "\u05D0\u05D1\u05D2\u05D3\u05D4"
@@ -1449,7 +1449,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_ltr_drag_endHandle() {
+    fun getTextSelectionInfo_bound_to_one_character_ltr_drag_endHandle() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1505,7 +1505,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_rtl_drag_endHandle() {
+    fun getTextSelectionInfo_bound_to_one_character_rtl_drag_endHandle() {
         with(defaultDensity) {
             val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
             val fontSize = 20.sp
@@ -1567,7 +1567,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_not_crossed() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_not_crossed() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1624,7 +1624,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_crossed() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_crossed() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1681,7 +1681,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_not_crossed_bounded() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_not_crossed_bounded() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1728,7 +1728,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_crossed_bounded() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_crossed_bounded() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1775,7 +1775,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_not_crossed_boundary() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_not_crossed_boundary() {
         with(defaultDensity) {
             val text = "hello world"
             val fontSize = 20.sp
@@ -1824,7 +1824,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_crossed_boundary() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_crossed_boundary() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1871,7 +1871,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_crossed() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_crossed() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1928,7 +1928,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_not_crossed_bounded() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_not_crossed_bounded() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -1975,7 +1975,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_crossed_bounded() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_crossed_bounded() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -2022,7 +2022,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_not_crossed_boundary() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_not_crossed_boundary() {
         with(defaultDensity) {
             val text = "hello world"
             val fontSize = 20.sp
@@ -2071,7 +2071,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_crossed_boundary() {
+    fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_crossed_boundary() {
         with(defaultDensity) {
             val text = "hello world"
             val fontSize = 20.sp
@@ -2120,7 +2120,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_cross_widget_not_contain_start() {
+    fun getTextSelectionInfo_cross_widget_not_contain_start() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
@@ -2160,7 +2160,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_cross_widget_not_contain_end() {
+    fun getTextSelectionInfo_cross_widget_not_contain_end() {
         with(defaultDensity) {
             val text = "hello world"
             val fontSize = 20.sp
@@ -2201,7 +2201,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_cross_widget_not_contain_start_handles_crossed() {
+    fun getTextSelectionInfo_cross_widget_not_contain_start_handles_crossed() {
         with(defaultDensity) {
             val text = "hello world"
             val fontSize = 20.sp
@@ -2243,7 +2243,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_cross_widget_not_contain_end_handles_crossed() {
+    fun getTextSelectionInfo_cross_widget_not_contain_end_handles_crossed() {
         with(defaultDensity) {
             val text = "hello world"
             val fontSize = 20.sp
@@ -2285,7 +2285,7 @@
     }
 
     @Test
-    fun testTextSelectionProcessor_not_selected() {
+    fun getTextSelectionInfo_not_selected() {
         with(defaultDensity) {
             val text = "hello world\n"
             val fontSize = 20.sp
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextFieldSelectionDelegateTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextFieldSelectionDelegateTest.kt
new file mode 100644
index 0000000..6b6a5e5
--- /dev/null
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextFieldSelectionDelegateTest.kt
@@ -0,0 +1,372 @@
+/*
+ * 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.selection
+
+import androidx.activity.ComponentActivity
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.ui.core.Constraints
+import androidx.ui.core.LayoutDirection
+import androidx.ui.test.android.AndroidComposeTestRule
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.InternalTextApi
+import androidx.ui.text.SpanStyle
+import androidx.ui.text.TextDelegate
+import androidx.ui.text.TextLayoutResult
+import androidx.ui.text.TextRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.font.asFontFamily
+import androidx.ui.unit.Density
+import androidx.ui.unit.TextUnit
+import androidx.ui.unit.sp
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(InternalTextApi::class)
+@RunWith(JUnit4::class)
+@SmallTest
+class TextFieldSelectionDelegateTest {
+    @get:Rule
+    val composeTestRule = AndroidComposeTestRule<ComponentActivity>()
+
+    private val fontFamily = BASIC_MEASURE_FONT.asFontFamily()
+    private val context = InstrumentationRegistry.getInstrumentation().context
+    private val defaultDensity = Density(density = 1f)
+    private val resourceLoader = TestFontResourceLoader(context)
+
+    @Test
+    fun getTextFieldSelection_long_press_select_word_ltr() {
+        val text = "hello world\n"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = 2,
+            rawEndOffset = 2,
+            previousSelection = null,
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = true
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(0)
+        Truth.assertThat(range.end).isEqualTo("hello".length)
+    }
+
+    @Test
+    fun getTextFieldSelection_long_press_select_word_rtl() {
+        val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = 5,
+            rawEndOffset = 5,
+            previousSelection = null,
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = true
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(text.indexOf("\u05D3"))
+        Truth.assertThat(range.end).isEqualTo(text.indexOf("\u05D5") + 1)
+    }
+
+    @Test
+    fun getTextFieldSelection_long_press_drag_handle_not_cross_select_word() {
+        val text = "hello world"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        val rawStartOffset = text.indexOf('e')
+        val rawEndOffset = text.indexOf('r')
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = rawStartOffset,
+            rawEndOffset = rawEndOffset,
+            previousSelection = null,
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = true
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(0)
+        Truth.assertThat(range.end).isEqualTo(text.length)
+    }
+
+    @Test
+    fun getTextFieldSelection_long_press_drag_handle_cross_select_word() {
+        val text = "hello world"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        val rawStartOffset = text.indexOf('r')
+        val rawEndOffset = text.indexOf('e')
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = rawStartOffset,
+            rawEndOffset = rawEndOffset,
+            previousSelection = null,
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = true
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(text.length)
+        Truth.assertThat(range.end).isEqualTo(0)
+    }
+
+    @Test
+    fun getTextFieldSelection_drag_select_range_ltr() {
+        val text = "hello world\n"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // "llo wor" is selected.
+        val startOffset = text.indexOf("l")
+        val endOffset = text.indexOf("r") + 1
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = TextRange(0, 0),
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = false
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(startOffset)
+        Truth.assertThat(range.end).isEqualTo(endOffset)
+    }
+
+    @Test
+    fun getTextFieldSelection_drag_select_range_rtl() {
+        val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // "\u05D1\u05D2 \u05D3" is selected.
+        val startOffset = text.indexOf("\u05D1")
+        val endOffset = text.indexOf("\u05D3") + 1
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = TextRange(0, 0),
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = false
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(startOffset)
+        Truth.assertThat(range.end).isEqualTo(endOffset)
+    }
+
+    @Test
+    fun getTextFieldSelection_drag_select_range_bidi() {
+        val textLtr = "Hello"
+        val textRtl = "\u05D0\u05D1\u05D2\u05D3\u05D4"
+        val text = textLtr + textRtl
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // "llo"+"\u05D0\u05D1\u05D2" is selected
+        val startOffset = text.indexOf("l")
+        val endOffset = text.indexOf("\u05D2") + 1
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = TextRange(0, 0),
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = false
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(startOffset)
+        Truth.assertThat(range.end).isEqualTo(endOffset)
+    }
+
+    @Test
+    fun getTextFieldSelection_drag_handles_crossed_ltr() {
+        val text = "hello world\n"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // "llo wor" is selected.
+        val startOffset = text.indexOf("r") + 1
+        val endOffset = text.indexOf("l")
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = TextRange(0, 0),
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = false
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(startOffset)
+        Truth.assertThat(range.end).isEqualTo(endOffset)
+    }
+
+    @Test
+    fun getTextFieldSelection_drag_handles_crossed_rtl() {
+        val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // "\u05D1\u05D2 \u05D3" is selected.
+        val startOffset = text.indexOf("\u05D3") + 1
+        val endOffset = text.indexOf("\u05D1")
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = TextRange(0, 0),
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = false
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(startOffset)
+        Truth.assertThat(range.end).isEqualTo(endOffset)
+    }
+
+    @Test
+    fun getTextFieldSelection_drag_handles_crossed_bidi() {
+        val textLtr = "Hello"
+        val textRtl = "\u05D0\u05D1\u05D2\u05D3\u05D4"
+        val text = textLtr + textRtl
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // "llo"+"\u05D0\u05D1\u05D2" is selected
+        val startOffset = text.indexOf("\u05D2") + 1
+        val endOffset = text.indexOf("l")
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = TextRange(0, 0),
+            previousHandlesCrossed = false,
+            isStartHandle = true,
+            wordBasedSelection = false
+        )
+
+        // Assert.
+        Truth.assertThat(range.start).isEqualTo(startOffset)
+        Truth.assertThat(range.end).isEqualTo(endOffset)
+    }
+
+    private fun simpleTextLayout(
+        text: String = "",
+        fontSize: TextUnit = TextUnit.Inherit,
+        density: Density
+    ): TextLayoutResult {
+        val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
+        val annotatedString = AnnotatedString(text, spanStyle)
+        return TextDelegate(
+            text = annotatedString,
+            style = TextStyle(),
+            density = density,
+            resourceLoader = resourceLoader
+        ).layout(Constraints(), LayoutDirection.Ltr)
+    }
+}
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 7d27dfa..844dc2a 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
@@ -40,7 +40,7 @@
 import androidx.ui.graphics.drawscope.drawCanvas
 import androidx.ui.graphics.Paint
 import androidx.ui.text.font.Font
-import androidx.ui.text.selection.TextSelectionDelegate
+import androidx.ui.text.selection.MultiWidgetSelectionDelegate
 import androidx.ui.text.style.TextAlign
 import androidx.ui.text.style.TextOverflow
 import androidx.ui.unit.Density
@@ -242,7 +242,7 @@
         val id: Selectable? =
             selectionRegistrar?.let {
                 selectionRegistrar.subscribe(
-                    TextSelectionDelegate(
+                    MultiWidgetSelectionDelegate(
                         selectionRangeUpdate = { state.selectionRange = it },
                         coordinatesCallback = { state.layoutCoordinates },
                         layoutResultCallback = { state.layoutResult }
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 e14be9b..0b1cd85 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
@@ -24,22 +24,26 @@
 import androidx.compose.remember
 import androidx.compose.setValue
 import androidx.compose.state
+import androidx.ui.core.ClipboardManagerAmbient
 import androidx.ui.core.DensityAmbient
 import androidx.ui.core.FontLoaderAmbient
+import androidx.ui.core.HapticFeedBackAmbient
 import androidx.ui.core.Layout
 import androidx.ui.core.LayoutCoordinates
 import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
 import androidx.ui.core.TextInputServiceAmbient
 import androidx.ui.core.drawBehind
-import androidx.ui.core.gesture.DragObserver
-import androidx.ui.core.gesture.dragGestureFilter
-import androidx.ui.core.gesture.pressIndicatorGestureFilter
 import androidx.ui.core.onPositioned
 import androidx.ui.core.focus.FocusModifier
 import androidx.ui.core.focus.FocusState
 import androidx.ui.core.focus.focusState
+import androidx.ui.core.gesture.DragObserver
+import androidx.ui.core.gesture.LongPressDragObserver
+import androidx.ui.core.gesture.dragGestureFilter
+import androidx.ui.core.gesture.longPressDragGestureFilter
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
 import androidx.ui.core.semantics.semantics
+import androidx.ui.geometry.Offset
 import androidx.ui.graphics.drawscope.drawCanvas
 import androidx.ui.input.EditProcessor
 import androidx.ui.input.TextFieldValue
@@ -48,7 +52,8 @@
 import androidx.ui.input.NO_SESSION
 import androidx.ui.input.VisualTransformation
 import androidx.ui.semantics.onClick
-import androidx.ui.geometry.Offset
+import androidx.ui.text.selection.TextFieldSelectionManager
+import androidx.ui.text.style.TextDirection
 import kotlin.math.roundToInt
 
 @Suppress("DEPRECATION")
@@ -72,14 +77,11 @@
     if (fullModel.value.text != value.text ||
         fullModel.value.selection != value.selection ||
         fullModel.value.composition != value.composition) {
-        val newSelection = TextRange(
-            value.selection.start.coerceIn(0, value.text.length),
-            value.selection.end.coerceIn(0, value.text.length)
-        )
+        @OptIn(InternalTextApi::class)
         fullModel.value = TextFieldValue(
             text = value.text,
-            selection = newSelection,
-            composition = value.composition
+            selection = value.selection.constrain(0, value.text.length),
+            composition = value.composition?.constrain(0, value.text.length)
         )
     }
 
@@ -211,23 +213,20 @@
         )
 
         // TODO: Stop lookup FocusModifier from modifier chain. (b/155434146)
-        var focusModifier: FocusModifier? = null
-        modifier.foldIn(Unit) { _, element ->
-            if (element is FocusModifier) {
-                focusModifier = element
-                return@foldIn
-            }
-        }
-
-        val updatedModifier = if (focusModifier == null) {
-            modifier + FocusModifier().also { focusModifier = it }
-        } else {
-            modifier
-        }
+        val focusModifier = chainedFocusModifier(modifier) ?: FocusModifier()
 
         state.processor.onNewState(value, textInputService, state.inputSession)
-        TextInputEventObserver(
-            focusModifier = focusModifier!!,
+
+        val manager = remember { TextFieldSelectionManager() }
+        manager.offsetMap = offsetMap
+        manager.onValueChange = onValueChangeWrapper
+        manager.state = state
+        manager.value = value
+        manager.clipboardManager = ClipboardManagerAmbient.current
+        manager.hapticFeedBack = HapticFeedBackAmbient.current
+
+        val observer = textInputEventObserver(
+            focusModifier = focusModifier,
             onPress = { },
             onFocus = {
                 state.hasFocus = true
@@ -278,79 +277,91 @@
                 onFocusChange(false)
             },
             onRelease = {
-                state.layoutResult?.let { layoutResult ->
-                    TextFieldDelegate.onRelease(
-                        it,
-                        layoutResult,
-                        state.processor,
-                        offsetMap,
-                        onValueChangeWrapper,
-                        textInputService,
-                        state.inputSession,
-                        state.hasFocus
-                    )
+                if (state.selectionIsOn == false) {
+                    state.layoutResult?.let { layoutResult ->
+                        TextFieldDelegate.onRelease(
+                            it,
+                            layoutResult,
+                            state.processor,
+                            offsetMap,
+                            onValueChangeWrapper,
+                            textInputService,
+                            state.inputSession,
+                            state.hasFocus
+                        )
+                    }
                 }
             },
+            state = state,
+            longPressDragObserver = manager.longPressDragObserver,
             imeAction = imeAction
-        ) {
-            Layout(
-                emptyContent(),
-                updatedModifier.drawBehind {
-                    state.layoutResult?.let { layoutResult ->
-                        drawCanvas { canvas, _ ->
-                            TextFieldDelegate.draw(
-                                canvas,
-                                value,
-                                offsetMap,
-                                layoutResult,
-                                DefaultSelectionColor
-                            )
-                        }
-                    }
-                }.onPositioned {
-                    if (textInputService != null) {
-                        state.layoutCoordinates = it
-                        state.layoutResult?.let { layoutResult ->
-                            TextFieldDelegate.notifyFocusedRect(
-                                value,
-                                state.textDelegate,
-                                layoutResult,
-                                it,
-                                textInputService,
-                                state.inputSession,
-                                state.hasFocus,
-                                offsetMap
-                            )
-                        }
-                    }
+        )
+
+        val drawModifier = Modifier.drawBehind {
+            state.layoutResult?.let { layoutResult ->
+                drawCanvas { canvas, _ ->
+                    TextFieldDelegate.draw(
+                        canvas,
+                        value,
+                        offsetMap,
+                        layoutResult,
+                        DefaultSelectionColor
+                    )
                 }
-            ) { _, constraints, layoutDirection ->
-                TextFieldDelegate.layout(
-                    state.textDelegate,
-                    constraints,
-                    layoutDirection,
-                    state.layoutResult
-                ).let { (width, height, result) ->
-                    if (state.layoutResult != result) {
-                        state.layoutResult = result
-                        onTextLayout(result)
-                    }
-                    layout(
-                        width,
-                        height,
-                        mapOf(
-                            FirstBaseline to result.firstBaseline.roundToInt(),
-                            LastBaseline to result.lastBaseline.roundToInt()
-                        )
-                    ) {}
+            }
+        }
+
+        val onPositionedModifier = Modifier.onPositioned {
+            if (textInputService != null) {
+                state.layoutCoordinates = it
+                state.layoutResult?.let { layoutResult ->
+                    TextFieldDelegate.notifyFocusedRect(
+                        value,
+                        state.textDelegate,
+                        layoutResult,
+                        it,
+                        textInputService,
+                        state.inputSession,
+                        state.hasFocus,
+                        offsetMap
+                    )
                 }
             }
         }
+
+        Layout(
+            emptyContent(),
+            modifier
+                .plus(observer)
+                .plus(focusModifier)
+                .plus(drawModifier)
+                .plus(onPositionedModifier)
+        ) { _, constraints, layoutDirection ->
+            TextFieldDelegate.layout(
+                state.textDelegate,
+                constraints,
+                layoutDirection,
+                state.layoutResult
+            ).let { (width, height, result) ->
+                if (state.layoutResult != result) {
+                    state.layoutResult = result
+                    onTextLayout(result)
+                }
+                layout(
+                    width,
+                    height,
+                    mapOf(
+                        FirstBaseline to result.firstBaseline.roundToInt(),
+                        LastBaseline to result.lastBaseline.roundToInt()
+                    )
+                ) {}
+            }
+        }
     }
 }
 
 @OptIn(InternalTextApi::class)
-private class TextFieldState(
+internal class TextFieldState(
     var textDelegate: TextDelegate
 ) {
     val processor = EditProcessor()
@@ -364,21 +375,48 @@
     var layoutCoordinates: LayoutCoordinates? = null
     /** The latest TextLayoutResult calculated in the measure block */
     var layoutResult: TextLayoutResult? = null
+    /**
+     * The gesture detector status, to indicate whether current status is selection or editing.
+     *
+     * In the editing mode, there is no selection shown, only cursor is shown. To enter the editing
+     * mode from selection mode, just tap on the screen.
+     *
+     * In the selection mode, there is no cursor shown, only selection is shown. To enter
+     * the selection mode, just long press on the screen. In this mode, finger movement on the
+     * screen changes selection instead of moving the cursor.
+     */
+    var selectionIsOn: Boolean = false
+    /** The [TextDirection] for the start of the selection. */
+    var selectionStartDirection: TextDirection = TextDirection.Ltr
+    /** The [TextDirection] for the end of the selection. */
+    var selectionEndDirection: TextDirection = TextDirection.Ltr
+}
+
+private fun chainedFocusModifier(modifier: Modifier): FocusModifier? {
+    var focusModifier: FocusModifier? = null
+    modifier.foldIn(Unit) { _, element ->
+        if (element is FocusModifier) {
+            focusModifier = element
+            return@foldIn
+        }
+    }
+    return focusModifier
 }
 
 /**
  * Helper composable for observing all text input related events.
  */
 @Composable
-private fun TextInputEventObserver(
+private fun textInputEventObserver(
     onPress: (Offset) -> Unit,
     onRelease: (Offset) -> Unit,
     onFocus: () -> Unit,
+    state: TextFieldState,
+    longPressDragObserver: LongPressDragObserver,
     onBlur: (hasNextClient: Boolean) -> Unit,
     focusModifier: FocusModifier,
-    imeAction: ImeAction,
-    children: @Composable () -> Unit
-) {
+    imeAction: ImeAction
+): Modifier {
     val prevState = state { FocusState.NotFocused }
     if (focusModifier.focusState == FocusState.Focused &&
         prevState.value == FocusState.NotFocused
@@ -404,8 +442,7 @@
         onBlur(false)
     }
 
-    val semantics = Modifier.semantics(applyToChildLayoutNode = true,
-        mergeAllDescendants = true,
+    val semantics = Modifier.semantics(mergeAllDescendants = true,
         properties = {
             this.imeAction = imeAction
             this.supportsInputMethods = true
@@ -413,22 +450,18 @@
         })
     val drag = Modifier.dragPositionGestureFilter(
         onPress = {
+            state.selectionIsOn = false
             if (focusModifier.focusState == FocusState.Focused) {
                 onPress(it)
             } else {
                 doFocusIn()
             }
         },
-        onRelease = onRelease
+        onRelease = onRelease,
+        longPressDragObserver = longPressDragObserver
     )
 
-    // TODO(b/150706555): This layout is temporary and should be removed once Semantics
-    //  is implemented with modifiers.
-    @Suppress("DEPRECATION")
-    PassThroughLayout(semantics) {
-        @Suppress("DEPRECATION")
-        PassThroughLayout(drag, children)
-    }
+    return semantics.plus(drag)
 }
 
 /**
@@ -472,7 +505,8 @@
 @Composable
 private fun Modifier.dragPositionGestureFilter(
     onPress: (Offset) -> Unit,
-    onRelease: (Offset) -> Unit
+    onRelease: (Offset) -> Unit,
+    longPressDragObserver: LongPressDragObserver
 ): Modifier {
     val tracker = state { DragEventTracker() }
     // TODO(shepshapard): PressIndicator doesn't seem to be the right thing to use here.  It
@@ -494,4 +528,5 @@
                 return Offset.Zero
             }
         })
+        .longPressDragGestureFilter(longPressDragObserver)
 }
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/MultiWidgetSelectionDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/MultiWidgetSelectionDelegate.kt
new file mode 100644
index 0000000..a06b97b
--- /dev/null
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/MultiWidgetSelectionDelegate.kt
@@ -0,0 +1,304 @@
+/*
+ * 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.selection
+
+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 kotlin.math.max
+
+internal class MultiWidgetSelectionDelegate(
+    private val selectionRangeUpdate: (TextRange?) -> Unit,
+    private val coordinatesCallback: () -> LayoutCoordinates?,
+    private val layoutResultCallback: () -> TextLayoutResult?
+) : Selectable {
+    override fun getSelection(
+        startPosition: Offset,
+        endPosition: Offset,
+        containerLayoutCoordinates: LayoutCoordinates,
+        longPress: Boolean,
+        previousSelection: Selection?,
+        isStartHandle: Boolean
+    ): Selection? {
+        val layoutCoordinates = getLayoutCoordinates() ?: return null
+        val textLayoutResult = layoutResultCallback() ?: return null
+
+        val relativePosition = containerLayoutCoordinates.childToLocal(
+            layoutCoordinates, Offset.Zero
+        )
+        val startPx = startPosition - relativePosition
+        val endPx = endPosition - relativePosition
+
+        val selection = getTextSelectionInfo(
+            textLayoutResult = textLayoutResult,
+            selectionCoordinates = Pair(startPx, endPx),
+            selectable = this,
+            wordBasedSelection = longPress,
+            previousSelection = previousSelection,
+            isStartHandle = isStartHandle
+        )
+
+        return if (selection == null) {
+            selectionRangeUpdate(null)
+            null
+        } else {
+            selectionRangeUpdate(selection.toTextRange())
+            return selection
+        }
+    }
+
+    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 Offset.Zero
+        }
+
+        if (getLayoutCoordinates() == null) return Offset.Zero
+
+        val textLayoutResult = layoutResultCallback() ?: return Offset.Zero
+        return getSelectionHandleCoordinates(
+            textLayoutResult = textLayoutResult,
+            offset = if (isStartHandle) selection.start.offset else selection.end.offset,
+            isStart = isStartHandle,
+            areHandlesCrossed = selection.handlesCrossed
+        )
+    }
+
+    override fun getLayoutCoordinates(): LayoutCoordinates? {
+        val layoutCoordinates = coordinatesCallback()
+        if (layoutCoordinates == null || !layoutCoordinates.isAttached) return null
+        return layoutCoordinates
+    }
+
+    override fun getText(): AnnotatedString {
+        val textLayoutResult = layoutResultCallback() ?: return AnnotatedString("")
+        return textLayoutResult.layoutInput.text
+    }
+
+    override fun getBoundingBox(offset: Int): Rect {
+        val textLayoutResult = layoutResultCallback() ?: return Rect.zero
+        return textLayoutResult.getBoundingBox(
+            offset.coerceIn(
+                0,
+                textLayoutResult.layoutInput.text.text.length - 1
+            )
+        )
+    }
+}
+
+/**
+ * Return information about the current selection in the Text.
+ *
+ * @param textLayoutResult a result of the text layout.
+ * @param selectionCoordinates The positions of the start and end of the selection in Text
+ * composable coordinate system.
+ * @param selectable current [Selectable] for which the [Selection] is being calculated
+ * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
+ * the selection is modified by long press and drag gesture, the result selection will be
+ * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
+ * selection.
+ * @param previousSelection previous selection result
+ * @param isStartHandle true if the start handle is being dragged
+ *
+ * @return [Selection] of the current composable, or null if the composable is not selected.
+ */
+internal fun getTextSelectionInfo(
+    textLayoutResult: TextLayoutResult,
+    selectionCoordinates: Pair<Offset, Offset>,
+    selectable: Selectable,
+    wordBasedSelection: Boolean,
+    previousSelection: Selection? = null,
+    isStartHandle: Boolean = true
+): Selection? {
+    val startPosition = selectionCoordinates.first
+    val endPosition = selectionCoordinates.second
+
+    val bounds = Rect(
+        0.0f,
+        0.0f,
+        textLayoutResult.size.width.toFloat(),
+        textLayoutResult.size.height.toFloat()
+    )
+
+    val lastOffset = textLayoutResult.layoutInput.text.text.length
+
+    val containsWholeSelectionStart =
+        bounds.contains(Offset(startPosition.x, startPosition.y))
+
+    val containsWholeSelectionEnd =
+        bounds.contains(Offset(endPosition.x, endPosition.y))
+
+    val rawStartOffset =
+        if (containsWholeSelectionStart)
+            textLayoutResult.getOffsetForPosition(startPosition).coerceIn(0, lastOffset)
+        else
+        // If the composable is selected, the start offset cannot be -1 for this composable. If the
+        // final start offset is still -1, it means this composable is not selected.
+            -1
+    val rawEndOffset =
+        if (containsWholeSelectionEnd)
+            textLayoutResult.getOffsetForPosition(endPosition).coerceIn(0, lastOffset)
+        else
+        // If the composable is selected, the end offset cannot be -1 for this composable. If the
+        // final end offset is still -1, it means this composable is not selected.
+            -1
+
+    return getRefinedSelectionInfo(
+        rawStartOffset = rawStartOffset,
+        rawEndOffset = rawEndOffset,
+        containsWholeSelectionStart = containsWholeSelectionStart,
+        containsWholeSelectionEnd = containsWholeSelectionEnd,
+        startPosition = startPosition,
+        endPosition = endPosition,
+        bounds = bounds,
+        textLayoutResult = textLayoutResult,
+        lastOffset = lastOffset,
+        selectable = selectable,
+        wordBasedSelection = wordBasedSelection,
+        previousSelection = previousSelection,
+        isStartHandle = isStartHandle
+    )
+}
+
+/**
+ * This method refines the selection info by processing the initial raw selection info.
+ *
+ * @param rawStartOffset unprocessed start offset calculated directly from input position
+ * @param rawEndOffset unprocessed end offset calculated directly from input position
+ * @param containsWholeSelectionStart a flag to check if current composable contains the overall
+ * selection start
+ * @param containsWholeSelectionEnd a flag to check if current composable contains the overall
+ * selection end
+ * @param startPosition graphical position of the start of the selection, in composable's
+ * coordinates.
+ * @param endPosition graphical position of the end of the selection, in composable's coordinates.
+ * @param bounds bounds of the current composable
+ * @param textLayoutResult a result of the text layout.
+ * @param lastOffset last offset of the text. It's actually the length of the text.
+ * @param selectable current [Selectable] for which the [Selection] is being calculated
+ * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
+ * the selection is modified by long press and drag gesture, the result selection will be
+ * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
+ * selection.
+ * @param previousSelection previous selection result
+ * @param isStartHandle true if the start handle is being dragged
+ *
+ * @return [Selection] of the current composable, or null if the composable is not selected.
+ */
+private fun getRefinedSelectionInfo(
+    rawStartOffset: Int,
+    rawEndOffset: Int,
+    containsWholeSelectionStart: Boolean,
+    containsWholeSelectionEnd: Boolean,
+    startPosition: Offset,
+    endPosition: Offset,
+    bounds: Rect,
+    textLayoutResult: TextLayoutResult,
+    lastOffset: Int,
+    selectable: Selectable,
+    wordBasedSelection: Boolean,
+    previousSelection: Selection? = null,
+    isStartHandle: Boolean = true
+): Selection? {
+    val shouldProcessAsSinglecomposable =
+        containsWholeSelectionStart && containsWholeSelectionEnd
+
+    var (startOffset, endOffset, handlesCrossed) =
+        if (shouldProcessAsSinglecomposable) {
+            processAsSingleComposable(
+                rawStartOffset = rawStartOffset,
+                rawEndOffset = rawEndOffset,
+                previousSelection = previousSelection?.toTextRange(),
+                isStartHandle = isStartHandle,
+                lastOffset = lastOffset,
+                handlesCrossed = previousSelection?.handlesCrossed ?: false
+            )
+        } else {
+            processCrossComposable(
+                startPosition = startPosition,
+                endPosition = endPosition,
+                rawStartOffset = rawStartOffset,
+                rawEndOffset = rawEndOffset,
+                lastOffset = lastOffset,
+                bounds = bounds,
+                containsWholeSelectionStart = containsWholeSelectionStart,
+                containsWholeSelectionEnd = containsWholeSelectionEnd
+            )
+        }
+    // nothing is selected
+    if (startOffset == -1 && endOffset == -1) return null
+
+    // If under long press, update the selection to word-based.
+    if (wordBasedSelection) {
+        val (start, end) = updateWordBasedSelection(
+            textLayoutResult = textLayoutResult,
+            startOffset = startOffset,
+            endOffset = endOffset,
+            handlesCrossed = handlesCrossed
+        )
+        startOffset = start
+        endOffset = end
+    }
+
+    return getAssembledSelectionInfo(
+        startOffset = startOffset,
+        endOffset = endOffset,
+        handlesCrossed = handlesCrossed,
+        selectable = selectable,
+        textLayoutResult = textLayoutResult
+    )
+}
+
+/**
+ * [Selection] contains a lot of parameters. It looks more clean to assemble an object of this
+ * class in a separate method.
+ *
+ * @param startOffset the final start offset to be returned.
+ * @param endOffset the final end offset to be returned.
+ * @param handlesCrossed true if the selection handles are crossed
+ * @param selectable current [Selectable] for which the [Selection] is being calculated
+ * @param textLayoutResult a result of the text layout.
+ *
+ * @return an assembled object of [Selection] using the offered selection info.
+ */
+private fun getAssembledSelectionInfo(
+    startOffset: Int,
+    endOffset: Int,
+    handlesCrossed: Boolean,
+    selectable: Selectable,
+    textLayoutResult: TextLayoutResult
+): Selection {
+    return Selection(
+        start = Selection.AnchorInfo(
+            direction = textLayoutResult.getBidiRunDirection(startOffset),
+            offset = startOffset,
+            selectable = selectable
+        ),
+        end = Selection.AnchorInfo(
+            direction = textLayoutResult.getBidiRunDirection(max(endOffset - 1, 0)),
+            offset = endOffset,
+            selectable = selectable
+        ),
+        handlesCrossed = handlesCrossed
+    )
+}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionDelegate.kt
new file mode 100644
index 0000000..7f6b907
--- /dev/null
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionDelegate.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.selection
+
+import androidx.ui.text.TextLayoutResult
+import androidx.ui.text.TextRange
+
+/**
+ * Return selection information for TextField.
+ *
+ * @param textLayoutResult a result of the text layout.
+ * @param rawStartOffset unprocessed start offset calculated directly from input position
+ * @param rawEndOffset unprocessed end offset calculated directly from input position
+ * @param previousSelection previous selection result
+ * @param previousHandlesCrossed true if the previous selection's handles are crossed
+ * @param isStartHandle true if the start handle is being dragged
+ * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
+ * the selection is modified by long press and drag gesture, the result selection will be
+ * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
+ * selection.
+ *
+ * @return selected text range.
+ */
+internal fun getTextFieldSelection(
+    textLayoutResult: TextLayoutResult?,
+    rawStartOffset: Int,
+    rawEndOffset: Int,
+    previousSelection: TextRange?,
+    previousHandlesCrossed: Boolean,
+    isStartHandle: Boolean,
+    wordBasedSelection: Boolean
+): TextRange {
+    textLayoutResult?.let {
+        val lastOffset = it.layoutInput.text.text.length
+
+        var (startOffset, endOffset, handlesCrossed) =
+            processAsSingleComposable(
+                rawStartOffset = rawStartOffset,
+                rawEndOffset = rawEndOffset,
+                previousSelection = previousSelection,
+                isStartHandle = isStartHandle,
+                lastOffset = lastOffset,
+                handlesCrossed = previousHandlesCrossed
+            )
+        if (wordBasedSelection) {
+            val (start, end) = updateWordBasedSelection(
+                textLayoutResult = it,
+                startOffset = startOffset,
+                endOffset = endOffset,
+                handlesCrossed = handlesCrossed
+            )
+            startOffset = start
+            endOffset = end
+        }
+
+        return TextRange(startOffset, endOffset)
+    }
+    return TextRange(0, 0)
+}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionManager.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionManager.kt
new file mode 100644
index 0000000..61de1f9
--- /dev/null
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionManager.kt
@@ -0,0 +1,243 @@
+/*
+ * 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.selection
+
+import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.gesture.LongPressDragObserver
+import androidx.ui.core.hapticfeedback.HapticFeedback
+import androidx.ui.core.hapticfeedback.HapticFeedbackType
+import androidx.ui.geometry.Offset
+import androidx.ui.input.OffsetMap
+import androidx.ui.input.TextFieldValue
+import androidx.ui.input.getSelectedText
+import androidx.ui.input.getTextAfterSelection
+import androidx.ui.input.getTextBeforeSelection
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.TextFieldState
+import androidx.ui.text.TextRange
+import kotlin.math.max
+
+/**
+ * A bridge class between user interaction to the text field selection.
+ */
+internal class TextFieldSelectionManager {
+
+    /**
+     * The current [OffsetMap] for text field.
+     */
+    internal var offsetMap: OffsetMap = OffsetMap.identityOffsetMap
+
+    /**
+     * Called when the input service updates the values in [TextFieldValue].
+     */
+    internal var onValueChange: (TextFieldValue) -> Unit = {}
+
+    /**
+     * The current [TextFieldState].
+     */
+    internal var state: TextFieldState? = null
+
+    /**
+     * The current [TextFieldValue].
+     */
+    internal var value: TextFieldValue = TextFieldValue()
+
+    /**
+     * [ClipboardManager] to perform clipboard features.
+     */
+    internal var clipboardManager: ClipboardManager? = null
+
+    /**
+     * [HapticFeedback] handle to perform haptic feedback.
+     */
+    var hapticFeedBack: HapticFeedback? = null
+
+    /**
+     * The beginning position of the drag gesture. Every time a new drag gesture starts, it wil be
+     * recalculated.
+     */
+    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 = Offset.Zero
+
+    /**
+     * [LongPressDragObserver] for long press and drag to select in TextField.
+     */
+    internal val longPressDragObserver = object : LongPressDragObserver {
+        override fun onLongPress(pxPosition: Offset) {
+            // selection never started
+            if (value.text == "") return
+            setSelectionStatus(true)
+            state?.layoutResult?.let { layoutResult ->
+                val offset = offsetMap.transformedToOriginal(
+                    layoutResult.getOffsetForPosition(pxPosition)
+                )
+                updateSelection(
+                    value = value,
+                    startOffset = offset,
+                    endOffset = offset,
+                    isStartHandle = true,
+                    wordBasedSelection = true
+                )
+            }
+            dragBeginPosition = pxPosition
+            dragTotalDistance = Offset.Zero
+        }
+
+        override fun onDrag(dragDistance: Offset): Offset {
+            // selection never started, did not consume any drag
+            if (value.text == "") return Offset.Zero
+
+            dragTotalDistance += dragDistance
+            state?.layoutResult?.let { layoutResult ->
+                val startOffset = layoutResult.getOffsetForPosition(dragBeginPosition)
+                val endOffset =
+                    layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
+                updateSelection(
+                    value = value,
+                    startOffset = startOffset,
+                    endOffset = endOffset,
+                    isStartHandle = true,
+                    wordBasedSelection = true
+                )
+            }
+            return dragDistance
+        }
+    }
+
+    /**
+     * The method for copying text.
+     *
+     * If there is no selection, return.
+     * Put the selected text into the [ClipboardManager], and cancel the selection.
+     * The text in the text field should be unchanged.
+     * The new cursor offset should be at the end of the previous selected text.
+     */
+    internal fun copy() {
+        if (value.selection.collapsed) return
+
+        clipboardManager?.setText(AnnotatedString(value.getSelectedText()))
+
+        val newCursorOffset = value.selection.end
+        val newValue = TextFieldValue(
+            text = value.text,
+            selection = TextRange(newCursorOffset, newCursorOffset)
+        )
+        onValueChange(newValue)
+        updateTextDirections(TextRange(newCursorOffset, newCursorOffset))
+        setSelectionStatus(false)
+    }
+
+    /**
+     * The method for pasting text.
+     *
+     * Get the text from [ClipboardManager]. If it's null, return.
+     * The new text should be the text before the selected text, plus the text from the
+     * [ClipboardManager], and plus the text after the selected text.
+     * Then the selection should collapse, and the new cursor offset should be the end of the
+     * newly added text.
+     */
+    internal fun paste() {
+        val text = clipboardManager?.getText()?.text ?: return
+
+        val newText = value.getTextBeforeSelection(value.text.length) +
+                text +
+                value.getTextAfterSelection(value.text.length)
+        val newCursorOffset = value.selection.start + text.length
+
+        val newValue = TextFieldValue(
+            text = newText,
+            selection = TextRange(newCursorOffset, newCursorOffset)
+        )
+        onValueChange(newValue)
+        updateTextDirections(TextRange(newCursorOffset, newCursorOffset))
+        setSelectionStatus(false)
+    }
+
+    /**
+     * The method for cutting text.
+     *
+     * If there is no selection, return.
+     * Put the selected text into the [ClipboardManager].
+     * The new text should be the text before the selection plus the text after the selection.
+     * And the new cursor offset should be between the text before the selection, and the text
+     * after the selection.
+     */
+    internal fun cut() {
+        if (value.selection.collapsed) return
+
+        clipboardManager?.setText(AnnotatedString(value.getSelectedText()))
+
+        val newText = value.getTextBeforeSelection(value.text.length) +
+                value.getTextAfterSelection(value.text.length)
+        val newCursorOffset = value.selection.start
+
+        val newValue = TextFieldValue(
+            text = newText,
+            selection = TextRange(newCursorOffset, newCursorOffset)
+        )
+        onValueChange(newValue)
+        updateTextDirections(TextRange(newCursorOffset, newCursorOffset))
+        setSelectionStatus(false)
+    }
+
+    private fun updateSelection(
+        value: TextFieldValue,
+        startOffset: Int,
+        endOffset: Int,
+        isStartHandle: Boolean,
+        wordBasedSelection: Boolean
+    ) {
+        val range = getTextFieldSelection(
+            textLayoutResult = state?.layoutResult,
+            rawStartOffset = startOffset,
+            rawEndOffset = endOffset,
+            previousSelection = if (value.selection.collapsed) null else value.selection,
+            previousHandlesCrossed = value.selection.reversed,
+            isStartHandle = isStartHandle,
+            wordBasedSelection = wordBasedSelection
+        )
+
+        if (range == value.selection) return
+
+        hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
+
+        val newValue = TextFieldValue(
+            text = value.text,
+            selection = range
+        )
+        onValueChange(newValue)
+        updateTextDirections(range)
+    }
+
+    private fun updateTextDirections(range: TextRange) {
+        state?.let {
+            it.selectionStartDirection = it.layoutResult!!.getBidiRunDirection(range.start)
+            it.selectionEndDirection = it.layoutResult!!.getBidiRunDirection(max(range.end - 1, 0))
+        }
+    }
+
+    private fun setSelectionStatus(on: Boolean) {
+        state?.let {
+            it.selectionIsOn = on
+        }
+    }
+}
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 5c56458..c26690a 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
@@ -16,292 +16,12 @@
 
 package androidx.ui.text.selection
 
-import androidx.ui.core.LayoutCoordinates
-import androidx.ui.core.selection.Selectable
-import androidx.ui.core.selection.Selection
 import androidx.ui.geometry.Rect
-import androidx.ui.text.AnnotatedString
 import androidx.ui.text.TextLayoutResult
 import androidx.ui.text.TextRange
 import androidx.ui.geometry.Offset
 import kotlin.math.max
 
-internal class TextSelectionDelegate(
-    private val selectionRangeUpdate: (TextRange?) -> Unit,
-    private val coordinatesCallback: () -> LayoutCoordinates?,
-    private val layoutResultCallback: () -> TextLayoutResult?
-) : Selectable {
-    override fun getSelection(
-        startPosition: Offset,
-        endPosition: Offset,
-        containerLayoutCoordinates: LayoutCoordinates,
-        longPress: Boolean,
-        previousSelection: Selection?,
-        isStartHandle: Boolean
-    ): Selection? {
-        val layoutCoordinates = getLayoutCoordinates() ?: return null
-        val textLayoutResult = layoutResultCallback() ?: return null
-
-        val relativePosition = containerLayoutCoordinates.childToLocal(
-            layoutCoordinates, Offset.Zero
-        )
-        val startPx = startPosition - relativePosition
-        val endPx = endPosition - relativePosition
-
-        val selection = getTextSelectionInfo(
-            textLayoutResult = textLayoutResult,
-            selectionCoordinates = Pair(startPx, endPx),
-            selectable = this,
-            wordBasedSelection = longPress,
-            previousSelection = previousSelection,
-            isStartHandle = isStartHandle
-        )
-
-        return if (selection == null) {
-            selectionRangeUpdate(null)
-            null
-        } else {
-            selectionRangeUpdate(selection.toTextRange())
-            return selection
-        }
-    }
-
-    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 Offset.Zero
-        }
-
-        if (getLayoutCoordinates() == null) return Offset.Zero
-
-        val textLayoutResult = layoutResultCallback() ?: return Offset.Zero
-        return getSelectionHandleCoordinates(
-            textLayoutResult = textLayoutResult,
-            offset = if (isStartHandle) selection.start.offset else selection.end.offset,
-            isStart = isStartHandle,
-            areHandlesCrossed = selection.handlesCrossed
-        )
-    }
-
-    override fun getLayoutCoordinates(): LayoutCoordinates? {
-        val layoutCoordinates = coordinatesCallback()
-        if (layoutCoordinates == null || !layoutCoordinates.isAttached) return null
-        return layoutCoordinates
-    }
-
-    override fun getText(): AnnotatedString {
-        val textLayoutResult = layoutResultCallback() ?: return AnnotatedString("")
-        return textLayoutResult.layoutInput.text
-    }
-
-    override fun getBoundingBox(offset: Int): Rect {
-        val textLayoutResult = layoutResultCallback() ?: return Rect.zero
-        return textLayoutResult.getBoundingBox(
-            offset.coerceIn(
-                0,
-                textLayoutResult.layoutInput.text.text.length - 1
-            )
-        )
-    }
-}
-
-/**
- * Return information about the current selection in the Text.
- *
- * @param textLayoutResult a result of the text layout.
- * @param selectionCoordinates The positions of the start and end of the selection in Text
- * composable coordinate system.
- * @param selectable current [Selectable] for which the [Selection] is being calculated
- * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
- * the selection is modified by long press and drag gesture, the result selection will be
- * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
- * selection.
- * @param previousSelection previous selection result
- * @param isStartHandle true if the start handle is being dragged
- *
- * @return [Selection] of the current composable, or null if the composable is not selected.
- */
-internal fun getTextSelectionInfo(
-    textLayoutResult: TextLayoutResult,
-    selectionCoordinates: Pair<Offset, Offset>,
-    selectable: Selectable,
-    wordBasedSelection: Boolean,
-    previousSelection: Selection? = null,
-    isStartHandle: Boolean = true
-): Selection? {
-    val startPosition = selectionCoordinates.first
-    val endPosition = selectionCoordinates.second
-
-    val bounds = Rect(
-        0.0f,
-        0.0f,
-        textLayoutResult.size.width.toFloat(),
-        textLayoutResult.size.height.toFloat()
-    )
-
-    val lastOffset = textLayoutResult.layoutInput.text.text.length
-
-    val containsWholeSelectionStart =
-        bounds.contains(Offset(startPosition.x, startPosition.y))
-
-    val containsWholeSelectionEnd =
-        bounds.contains(Offset(endPosition.x, endPosition.y))
-
-    val rawStartOffset =
-        if (containsWholeSelectionStart)
-            textLayoutResult.getOffsetForPosition(startPosition).coerceIn(0, lastOffset)
-        else
-        // If the composable is selected, the start offset cannot be -1 for this composable. If the
-        // final start offset is still -1, it means this composable is not selected.
-            -1
-    val rawEndOffset =
-        if (containsWholeSelectionEnd)
-            textLayoutResult.getOffsetForPosition(endPosition).coerceIn(0, lastOffset)
-        else
-        // If the composable is selected, the end offset cannot be -1 for this composable. If the
-        // final end offset is still -1, it means this composable is not selected.
-            -1
-
-    return getRefinedSelectionInfo(
-        rawStartOffset = rawStartOffset,
-        rawEndOffset = rawEndOffset,
-        containsWholeSelectionStart = containsWholeSelectionStart,
-        containsWholeSelectionEnd = containsWholeSelectionEnd,
-        startPosition = startPosition,
-        endPosition = endPosition,
-        bounds = bounds,
-        textLayoutResult = textLayoutResult,
-        lastOffset = lastOffset,
-        selectable = selectable,
-        wordBasedSelection = wordBasedSelection,
-        previousSelection = previousSelection,
-        isStartHandle = isStartHandle
-    )
-}
-
-/**
- * This method refines the selection info by processing the initial raw selection info.
- *
- * @param rawStartOffset unprocessed start offset calculated directly from input position
- * @param rawEndOffset unprocessed end offset calculated directly from input position
- * @param containsWholeSelectionStart a flag to check if current composable contains the overall
- * selection start
- * @param containsWholeSelectionEnd a flag to check if current composable contains the overall
- * selection end
- * @param startPosition graphical position of the start of the selection, in composable's
- * coordinates.
- * @param endPosition graphical position of the end of the selection, in composable's coordinates.
- * @param bounds bounds of the current composable
- * @param textLayoutResult a result of the text layout.
- * @param lastOffset last offset of the text. It's actually the length of the text.
- * @param selectable current [Selectable] for which the [Selection] is being calculated
- * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
- * the selection is modified by long press and drag gesture, the result selection will be
- * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
- * selection.
- * @param previousSelection previous selection result
- * @param isStartHandle true if the start handle is being dragged
- *
- * @return [Selection] of the current composable, or null if the composable is not selected.
- */
-private fun getRefinedSelectionInfo(
-    rawStartOffset: Int,
-    rawEndOffset: Int,
-    containsWholeSelectionStart: Boolean,
-    containsWholeSelectionEnd: Boolean,
-    startPosition: Offset,
-    endPosition: Offset,
-    bounds: Rect,
-    textLayoutResult: TextLayoutResult,
-    lastOffset: Int,
-    selectable: Selectable,
-    wordBasedSelection: Boolean,
-    previousSelection: Selection? = null,
-    isStartHandle: Boolean = true
-): Selection? {
-    val shouldProcessAsSinglecomposable =
-        containsWholeSelectionStart && containsWholeSelectionEnd
-
-    var (startOffset, endOffset, handlesCrossed) =
-        if (shouldProcessAsSinglecomposable) {
-            processAsSingleComposable(
-                rawStartOffset = rawStartOffset,
-                rawEndOffset = rawEndOffset,
-                previousSelection = previousSelection,
-                isStartHandle = isStartHandle,
-                lastOffset = lastOffset
-            )
-        } else {
-            processCrossComposable(
-                startPosition = startPosition,
-                endPosition = endPosition,
-                rawStartOffset = rawStartOffset,
-                rawEndOffset = rawEndOffset,
-                lastOffset = lastOffset,
-                bounds = bounds,
-                containsWholeSelectionStart = containsWholeSelectionStart,
-                containsWholeSelectionEnd = containsWholeSelectionEnd
-            )
-        }
-    // nothing is selected
-    if (startOffset == -1 && endOffset == -1) return null
-
-    // If under long press, update the selection to word-based.
-    if (wordBasedSelection) {
-        val (start, end) = updateWordBasedSelection(
-            textLayoutResult = textLayoutResult,
-            startOffset = startOffset,
-            endOffset = endOffset,
-            handlesCrossed = handlesCrossed
-        )
-        startOffset = start
-        endOffset = end
-    }
-
-    return getAssembledSelectionInfo(
-        startOffset = startOffset,
-        endOffset = endOffset,
-        handlesCrossed = handlesCrossed,
-        selectable = selectable,
-        textLayoutResult = textLayoutResult
-    )
-}
-
-/**
- * [Selection] contains a lot of parameters. It looks more clean to assemble an object of this
- * class in a separate method.
- *
- * @param startOffset the final start offset to be returned.
- * @param endOffset the final end offset to be returned.
- * @param handlesCrossed true if the selection handles are crossed
- * @param selectable current [Selectable] for which the [Selection] is being calculated
- * @param textLayoutResult a result of the text layout.
- *
- * @return an assembled object of [Selection] using the offered selection info.
- */
-private fun getAssembledSelectionInfo(
-    startOffset: Int,
-    endOffset: Int,
-    handlesCrossed: Boolean,
-    selectable: Selectable,
-    textLayoutResult: TextLayoutResult
-): Selection {
-    return Selection(
-        start = Selection.AnchorInfo(
-            direction = textLayoutResult.getBidiRunDirection(startOffset),
-            offset = startOffset,
-            selectable = selectable
-        ),
-        end = Selection.AnchorInfo(
-            direction = textLayoutResult.getBidiRunDirection(max(endOffset - 1, 0)),
-            offset = endOffset,
-            selectable = selectable
-        ),
-        handlesCrossed = handlesCrossed
-    )
-}
-
 /**
  * This method takes unprocessed selection information as input, and calculates the selection
  * range and check if the selection handles are crossed, for selection with both start and end
@@ -312,28 +32,34 @@
  * different location. If the selection anchors point the same location and this is true, the
  * result selection will be adjusted to word boundary. Otherwise, the selection will be adjusted
  * to keep single character selected.
- * @param previousSelection previous selection result
+ * @param previousSelection previous selected text range.
  * @param isStartHandle true if the start handle is being dragged
  * @param lastOffset last offset of the text. It's actually the length of the text.
+ * @param handlesCrossed true if the selection handles are crossed
  *
  * @return the final startOffset, endOffset of the selection, and if the start and end are
  * crossed each other.
  */
-private fun processAsSingleComposable(
+internal fun processAsSingleComposable(
     rawStartOffset: Int,
     rawEndOffset: Int,
-    previousSelection: Selection?,
+    previousSelection: TextRange?,
     isStartHandle: Boolean,
-    lastOffset: Int
+    lastOffset: Int,
+    handlesCrossed: Boolean
 ): Triple<Int, Int, Boolean> {
     var startOffset = rawStartOffset
     var endOffset = rawEndOffset
     if (startOffset == endOffset) {
+
+        // If the start and end offset are at the same character, and it's not the initial
+        // selection, then bound to at least one character.
         val textRange = ensureAtLeastOneChar(
             offset = rawStartOffset,
             lastOffset = lastOffset,
             previousSelection = previousSelection,
-            isStartHandle = isStartHandle
+            isStartHandle = isStartHandle,
+            handlesCrossed = handlesCrossed
         )
         startOffset = textRange.start
         endOffset = textRange.end
@@ -363,7 +89,7 @@
  * @return the final startOffset, endOffset of the selection, and if the start and end handles are
  * crossed each other.
  */
-private fun processCrossComposable(
+internal fun processCrossComposable(
     startPosition: Offset,
     endPosition: Offset,
     rawStartOffset: Int,
@@ -414,7 +140,7 @@
  *
  * @return the adjusted word-based start and end offset of the selection.
  */
-private fun updateWordBasedSelection(
+internal fun updateWordBasedSelection(
     textLayoutResult: TextLayoutResult,
     startOffset: Int,
     endOffset: Int,
@@ -442,33 +168,33 @@
  * @param offset unprocessed start and end offset calculated directly from input position, in
  * this case start and offset equals to each other.
  * @param lastOffset last offset of the text. It's actually the length of the text.
- * @param previousSelection previous selection result
+ * @param previousSelection previous selected text range.
  * @param isStartHandle true if the start handle is being dragged
+ * @param handlesCrossed true if the selection handles are crossed
  *
  * @return the adjusted [TextRange].
  */
 private fun ensureAtLeastOneChar(
     offset: Int,
     lastOffset: Int,
-    previousSelection: Selection?,
-    isStartHandle: Boolean
+    previousSelection: TextRange?,
+    isStartHandle: Boolean,
+    handlesCrossed: Boolean
 ): TextRange {
     var newStartOffset = offset
     var newEndOffset = offset
 
-    // If the start and end offset are at the same character, and it's not the
-    // initial selection, then bound to at least one character.
     previousSelection?.let {
         if (isStartHandle) {
             newStartOffset =
-                if (it.handlesCrossed) {
-                    if (newEndOffset == 0 || it.start.offset == newEndOffset + 1) {
+                if (handlesCrossed) {
+                    if (newEndOffset == 0 || it.start == newEndOffset + 1) {
                         newEndOffset + 1
                     } else {
                         newEndOffset - 1
                     }
                 } else {
-                    if (newEndOffset == lastOffset || it.start.offset == newEndOffset - 1) {
+                    if (newEndOffset == lastOffset || it.start == newEndOffset - 1) {
                         newEndOffset - 1
                     } else {
                         newEndOffset + 1
@@ -476,14 +202,16 @@
                 }
         } else {
             newEndOffset =
-                if (it.handlesCrossed) {
-                    if (newStartOffset == lastOffset || it.end.offset == newStartOffset - 1) {
+                if (handlesCrossed) {
+                    if (
+                        newStartOffset == lastOffset || it.end == newStartOffset - 1
+                    ) {
                         newStartOffset - 1
                     } else {
                         newStartOffset + 1
                     }
                 } else {
-                    if (newStartOffset == 0 || it.end.offset == newStartOffset + 1) {
+                    if (newStartOffset == 0 || it.end == newStartOffset + 1) {
                         newStartOffset + 1
                     } else {
                         newStartOffset - 1
@@ -505,7 +233,7 @@
  *
  * @return the graphical position where the selection handle should be.
  */
-private fun getSelectionHandleCoordinates(
+internal fun getSelectionHandleCoordinates(
     textLayoutResult: TextLayoutResult,
     offset: Int,
     isStart: Boolean,
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/selection/TextFieldSelectionManagerTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/selection/TextFieldSelectionManagerTest.kt
new file mode 100644
index 0000000..c385596
--- /dev/null
+++ b/ui/ui-text/src/test/java/androidx/ui/text/selection/TextFieldSelectionManagerTest.kt
@@ -0,0 +1,211 @@
+/*
+ * 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.selection
+
+import androidx.test.filters.SmallTest
+import androidx.ui.core.Constraints
+import androidx.ui.core.LayoutDirection
+import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.hapticfeedback.HapticFeedback
+import androidx.ui.core.hapticfeedback.HapticFeedbackType
+import androidx.ui.geometry.Offset
+import androidx.ui.input.OffsetMap
+import androidx.ui.input.TextFieldValue
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.TextFieldState
+import androidx.ui.text.TextLayoutInput
+import androidx.ui.text.TextRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.style.TextDirection
+import androidx.ui.text.style.TextOverflow
+import androidx.ui.unit.Density
+import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.spy
+import com.nhaarman.mockitokotlin2.times
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.whenever
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class TextFieldSelectionManagerTest {
+    private val text = "Hello World"
+    private val density = Density(density = 1f)
+    private val offsetMap = OffsetMap.identityOffsetMap
+    private var value = TextFieldValue(text)
+    private val lambda: (TextFieldValue) -> Unit = { value = it }
+    private val spyLambda = spy(lambda)
+    private val state = TextFieldState(mock())
+
+    private val dragBeginPosition = Offset.Zero
+    private val dragDistance = Offset(300f, 15f)
+    private val beginOffset = 0
+    private val dragOffset = text.indexOf('W')
+    private val longPressTextRange = TextRange(0, "Hello".length)
+    private val dragTextRange = TextRange("Hello".length + 1, text.length)
+
+    private val manager = TextFieldSelectionManager()
+
+    private val clipboardManager = mock<ClipboardManager>()
+    private val hapticFeedback = mock<HapticFeedback>()
+
+    @Before
+    fun setup() {
+        manager.offsetMap = offsetMap
+        manager.onValueChange = lambda
+        manager.state = state
+        manager.value = value
+        manager.clipboardManager = clipboardManager
+        manager.hapticFeedBack = hapticFeedback
+
+        state.layoutResult = mock()
+        whenever(state.layoutResult!!.layoutInput).thenReturn(
+            TextLayoutInput(
+                text = AnnotatedString(text),
+                style = TextStyle.Default,
+                placeholders = mock(),
+                maxLines = 2,
+                softWrap = true,
+                overflow = TextOverflow.Ellipsis,
+                density = density,
+                layoutDirection = LayoutDirection.Ltr,
+                resourceLoader = mock(),
+                constraints = Constraints()
+            )
+        )
+        whenever(state.layoutResult!!.getOffsetForPosition(dragBeginPosition)).thenReturn(
+            beginOffset
+        )
+        whenever(state.layoutResult!!.getOffsetForPosition(dragDistance)).thenReturn(dragOffset)
+        whenever(state.layoutResult!!.getWordBoundary(beginOffset)).thenReturn(longPressTextRange)
+        whenever(state.layoutResult!!.getWordBoundary(dragOffset)).thenReturn(dragTextRange)
+        whenever(state.layoutResult!!.getBidiRunDirection(any())).thenReturn(TextDirection.Ltr)
+    }
+
+    @Test
+    fun TextFieldSelectionManager_init() {
+        assertThat(manager.offsetMap).isEqualTo(offsetMap)
+        assertThat(manager.onValueChange).isEqualTo(lambda)
+        assertThat(manager.state).isEqualTo(state)
+        assertThat(manager.value).isEqualTo(value)
+    }
+
+    @Test
+    fun TextFieldSelectionManager_longPressDragObserver_onLongPress() {
+        manager.longPressDragObserver.onLongPress(dragBeginPosition)
+
+        assertThat(state.selectionIsOn).isTrue()
+        assertThat(value.selection).isEqualTo(longPressTextRange)
+        verify(
+            hapticFeedback,
+            times(1)
+        ).performHapticFeedback(HapticFeedbackType.TextHandleMove)
+    }
+
+    @Test
+    fun TextFieldSelectionManager_longPressDragObserver_onDrag() {
+        manager.longPressDragObserver.onLongPress(dragBeginPosition)
+        manager.longPressDragObserver.onDrag(dragDistance)
+
+        assertThat(value.selection).isEqualTo(TextRange(0, text.length))
+        verify(
+            hapticFeedback,
+            times(2)
+        ).performHapticFeedback(HapticFeedbackType.TextHandleMove)
+    }
+
+    @Test
+    fun copy_selection_collapse() {
+        manager.value = TextFieldValue(text = text, selection = TextRange(4, 4))
+
+        manager.copy()
+
+        verify(clipboardManager, times(0)).setText(any())
+    }
+
+    @Test
+    fun copy_selection_not_null() {
+        manager.value = TextFieldValue(text = text, selection = TextRange(0, "Hello".length))
+
+        manager.copy()
+
+        verify(clipboardManager, times(1)).setText(AnnotatedString("Hello"))
+        assertThat(value.selection).isEqualTo(TextRange("Hello".length, "Hello".length))
+        assertThat(state.selectionIsOn).isFalse()
+    }
+
+    @Test
+    fun paste_clipBoardManager_null() {
+        manager.clipboardManager = null
+
+        manager.paste()
+
+        verify(spyLambda, times(0)).invoke(any())
+    }
+
+    @Test
+    fun paste_clipBoardManager_empty() {
+        whenever(clipboardManager.getText()).thenReturn(null)
+
+        manager.paste()
+
+        verify(spyLambda, times(0)).invoke(any())
+    }
+
+    @Test
+    fun paste_clipBoardManager_not_empty() {
+        whenever(clipboardManager.getText()).thenReturn(AnnotatedString("Hello"))
+        manager.value = TextFieldValue(
+            text = text,
+            selection = TextRange("Hel".length, "Hello Wo".length)
+        )
+
+        manager.paste()
+
+        assertThat(value.text).isEqualTo("HelHellorld")
+        assertThat(value.selection).isEqualTo(TextRange("Hello Wo".length, "Hello Wo".length))
+        assertThat(state.selectionIsOn).isFalse()
+    }
+
+    @Test
+    fun cut_selection_collapse() {
+        manager.value = TextFieldValue(text = text, selection = TextRange(4, 4))
+
+        manager.cut()
+
+        verify(clipboardManager, times(0)).setText(any())
+    }
+
+    @Test
+    fun cut_selection_not_null() {
+        manager.value = TextFieldValue(
+            text = text + text,
+            selection = TextRange("Hello".length, text.length))
+
+        manager.cut()
+
+        verify(clipboardManager, times(1)).setText(AnnotatedString(" World"))
+        assertThat(value.text).isEqualTo("HelloHello World")
+        assertThat(value.selection).isEqualTo(TextRange("Hello".length, "Hello".length))
+        assertThat(state.selectionIsOn).isFalse()
+    }
+}
diff --git a/ui/ui-tooling/OWNERS b/ui/ui-tooling/OWNERS
index 583d415..36d6fce 100644
--- a/ui/ui-tooling/OWNERS
+++ b/ui/ui-tooling/OWNERS
@@ -1,3 +1,4 @@
 [email protected]
 [email protected]
[email protected]
\ No newline at end of file
[email protected]
[email protected]
\ No newline at end of file
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/animation/PreviewAnimationClockTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
similarity index 94%
rename from ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/animation/PreviewAnimationClockTest.kt
rename to ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
index ca6a8ce..e6dbd0a 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/animation/PreviewAnimationClockTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.ui.tooling.animation
+package androidx.ui.tooling.preview.animation
 
 import androidx.animation.AnimationClockObserver
-import androidx.ui.tooling.preview.animation.PreviewAnimationClock
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
diff --git a/ui/ui-unit/api/0.1.0-dev15.txt b/ui/ui-unit/api/0.1.0-dev15.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/0.1.0-dev15.txt
+++ b/ui/ui-unit/api/0.1.0-dev15.txt
@@ -17,7 +17,7 @@
     property public final int maxWidth;
     property public final int minHeight;
     property public final int minWidth;
-    field public static final androidx.ui.core.Constraints.Companion! Companion;
+    field public static final androidx.ui.core.Constraints.Companion Companion;
     field public static final int Infinity = 2147483647; // 0x7fffffff
   }
 
@@ -41,6 +41,8 @@
   }
 
   public enum LayoutDirection {
+    method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutDirection[] values();
     enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
     enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
   }
@@ -108,7 +110,7 @@
     method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float 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.Dp.Companion! Companion;
+    field public static final androidx.ui.unit.Dp.Companion Companion;
   }
 
   public static final class Dp.Companion {
@@ -214,7 +216,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
-    field public static final androidx.ui.unit.Duration.Companion! Companion;
+    field public static final androidx.ui.unit.Duration.Companion Companion;
   }
 
   public static final class Duration.Companion {
@@ -268,7 +270,7 @@
     method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
     property public final int x;
     property public final int y;
-    field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+    field public static final androidx.ui.unit.IntOffset.Companion Companion;
   }
 
   public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
     property public final int height;
     property public final int width;
-    field public static final androidx.ui.unit.IntSize.Companion! Companion;
+    field public static final androidx.ui.unit.IntSize.Companion Companion;
   }
 
   public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
     method public static inline operator long times-impl(long $this, int other);
     method public static String toString-impl(long $this);
     method public static inline operator long unaryMinus-impl(long $this);
-    field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+    field public static final androidx.ui.unit.TextUnit.Companion Companion;
   }
 
   public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
   }
 
   public enum TextUnitType {
+    method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.unit.TextUnitType[] values();
     enum_constant public static final androidx.ui.unit.TextUnitType Em;
     enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
     enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
     method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
     method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
     method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
-    field public static final androidx.ui.unit.Uptime.Companion! Companion;
+    field public static final androidx.ui.unit.Uptime.Companion Companion;
   }
 
   public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
     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;
+    field public static final androidx.ui.unit.Velocity.Companion Companion;
   }
 
   public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/api_lint.ignore b/ui/ui-unit/api/api_lint.ignore
index aad744b..319f1ff 100644
--- a/ui/ui-unit/api/api_lint.ignore
+++ b/ui/ui-unit/api/api_lint.ignore
@@ -1,7 +1,3 @@
 // Baseline format: 1.0
 MethodNameUnits: androidx.ui.unit.Durations#inSeconds(androidx.ui.unit.Duration):
     Returned time values must be in milliseconds, was `inSeconds`
-
-
-MissingNullability: androidx.ui.core.Constraints2#toString-impl(long):
-    Missing nullability on method `toString-impl` return
diff --git a/ui/ui-unit/api/current.txt b/ui/ui-unit/api/current.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/current.txt
+++ b/ui/ui-unit/api/current.txt
@@ -17,7 +17,7 @@
     property public final int maxWidth;
     property public final int minHeight;
     property public final int minWidth;
-    field public static final androidx.ui.core.Constraints.Companion! Companion;
+    field public static final androidx.ui.core.Constraints.Companion Companion;
     field public static final int Infinity = 2147483647; // 0x7fffffff
   }
 
@@ -41,6 +41,8 @@
   }
 
   public enum LayoutDirection {
+    method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutDirection[] values();
     enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
     enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
   }
@@ -108,7 +110,7 @@
     method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float 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.Dp.Companion! Companion;
+    field public static final androidx.ui.unit.Dp.Companion Companion;
   }
 
   public static final class Dp.Companion {
@@ -214,7 +216,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
-    field public static final androidx.ui.unit.Duration.Companion! Companion;
+    field public static final androidx.ui.unit.Duration.Companion Companion;
   }
 
   public static final class Duration.Companion {
@@ -268,7 +270,7 @@
     method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
     property public final int x;
     property public final int y;
-    field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+    field public static final androidx.ui.unit.IntOffset.Companion Companion;
   }
 
   public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
     property public final int height;
     property public final int width;
-    field public static final androidx.ui.unit.IntSize.Companion! Companion;
+    field public static final androidx.ui.unit.IntSize.Companion Companion;
   }
 
   public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
     method public static inline operator long times-impl(long $this, int other);
     method public static String toString-impl(long $this);
     method public static inline operator long unaryMinus-impl(long $this);
-    field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+    field public static final androidx.ui.unit.TextUnit.Companion Companion;
   }
 
   public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
   }
 
   public enum TextUnitType {
+    method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.unit.TextUnitType[] values();
     enum_constant public static final androidx.ui.unit.TextUnitType Em;
     enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
     enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
     method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
     method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
     method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
-    field public static final androidx.ui.unit.Uptime.Companion! Companion;
+    field public static final androidx.ui.unit.Uptime.Companion Companion;
   }
 
   public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
     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;
+    field public static final androidx.ui.unit.Velocity.Companion Companion;
   }
 
   public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
     property public final int maxWidth;
     property public final int minHeight;
     property public final int minWidth;
-    field public static final androidx.ui.core.Constraints.Companion! Companion;
+    field public static final androidx.ui.core.Constraints.Companion Companion;
     field public static final int Infinity = 2147483647; // 0x7fffffff
   }
 
@@ -41,6 +41,8 @@
   }
 
   public enum LayoutDirection {
+    method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutDirection[] values();
     enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
     enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
   }
@@ -108,7 +110,7 @@
     method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float 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.Dp.Companion! Companion;
+    field public static final androidx.ui.unit.Dp.Companion Companion;
   }
 
   public static final class Dp.Companion {
@@ -214,7 +216,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
-    field public static final androidx.ui.unit.Duration.Companion! Companion;
+    field public static final androidx.ui.unit.Duration.Companion Companion;
   }
 
   public static final class Duration.Companion {
@@ -268,7 +270,7 @@
     method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
     property public final int x;
     property public final int y;
-    field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+    field public static final androidx.ui.unit.IntOffset.Companion Companion;
   }
 
   public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
     property public final int height;
     property public final int width;
-    field public static final androidx.ui.unit.IntSize.Companion! Companion;
+    field public static final androidx.ui.unit.IntSize.Companion Companion;
   }
 
   public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
     method public static inline operator long times-impl(long $this, int other);
     method public static String toString-impl(long $this);
     method public static inline operator long unaryMinus-impl(long $this);
-    field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+    field public static final androidx.ui.unit.TextUnit.Companion Companion;
   }
 
   public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
   }
 
   public enum TextUnitType {
+    method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.unit.TextUnitType[] values();
     enum_constant public static final androidx.ui.unit.TextUnitType Em;
     enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
     enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
     method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
     method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
     method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
-    field public static final androidx.ui.unit.Uptime.Companion! Companion;
+    field public static final androidx.ui.unit.Uptime.Companion Companion;
   }
 
   public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
     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;
+    field public static final androidx.ui.unit.Velocity.Companion Companion;
   }
 
   public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/public_plus_experimental_current.txt b/ui/ui-unit/api/public_plus_experimental_current.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/public_plus_experimental_current.txt
+++ b/ui/ui-unit/api/public_plus_experimental_current.txt
@@ -17,7 +17,7 @@
     property public final int maxWidth;
     property public final int minHeight;
     property public final int minWidth;
-    field public static final androidx.ui.core.Constraints.Companion! Companion;
+    field public static final androidx.ui.core.Constraints.Companion Companion;
     field public static final int Infinity = 2147483647; // 0x7fffffff
   }
 
@@ -41,6 +41,8 @@
   }
 
   public enum LayoutDirection {
+    method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutDirection[] values();
     enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
     enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
   }
@@ -108,7 +110,7 @@
     method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float 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.Dp.Companion! Companion;
+    field public static final androidx.ui.unit.Dp.Companion Companion;
   }
 
   public static final class Dp.Companion {
@@ -214,7 +216,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
-    field public static final androidx.ui.unit.Duration.Companion! Companion;
+    field public static final androidx.ui.unit.Duration.Companion Companion;
   }
 
   public static final class Duration.Companion {
@@ -268,7 +270,7 @@
     method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
     property public final int x;
     property public final int y;
-    field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+    field public static final androidx.ui.unit.IntOffset.Companion Companion;
   }
 
   public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
     property public final int height;
     property public final int width;
-    field public static final androidx.ui.unit.IntSize.Companion! Companion;
+    field public static final androidx.ui.unit.IntSize.Companion Companion;
   }
 
   public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
     method public static inline operator long times-impl(long $this, int other);
     method public static String toString-impl(long $this);
     method public static inline operator long unaryMinus-impl(long $this);
-    field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+    field public static final androidx.ui.unit.TextUnit.Companion Companion;
   }
 
   public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
   }
 
   public enum TextUnitType {
+    method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.unit.TextUnitType[] values();
     enum_constant public static final androidx.ui.unit.TextUnitType Em;
     enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
     enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
     method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
     method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
     method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
-    field public static final androidx.ui.unit.Uptime.Companion! Companion;
+    field public static final androidx.ui.unit.Uptime.Companion Companion;
   }
 
   public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
     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;
+    field public static final androidx.ui.unit.Velocity.Companion Companion;
   }
 
   public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/restricted_0.1.0-dev15.txt b/ui/ui-unit/api/restricted_0.1.0-dev15.txt
index 82aef00..29c348b 100644
--- a/ui/ui-unit/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-unit/api/restricted_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
     property public final int maxWidth;
     property public final int minHeight;
     property public final int minWidth;
-    field public static final androidx.ui.core.Constraints.Companion! Companion;
+    field public static final androidx.ui.core.Constraints.Companion Companion;
     field public static final int Infinity = 2147483647; // 0x7fffffff
   }
 
@@ -41,6 +41,8 @@
   }
 
   public enum LayoutDirection {
+    method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutDirection[] values();
     enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
     enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
   }
@@ -108,7 +110,7 @@
     method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float 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.Dp.Companion! Companion;
+    field public static final androidx.ui.unit.Dp.Companion Companion;
   }
 
   public static final class Dp.Companion {
@@ -214,7 +216,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
-    field public static final androidx.ui.unit.Duration.Companion! Companion;
+    field public static final androidx.ui.unit.Duration.Companion Companion;
   }
 
   public static final class Duration.Companion {
@@ -268,7 +270,7 @@
     method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
     property public final int x;
     property public final int y;
-    field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+    field public static final androidx.ui.unit.IntOffset.Companion Companion;
   }
 
   public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
     property public final int height;
     property public final int width;
-    field public static final androidx.ui.unit.IntSize.Companion! Companion;
+    field public static final androidx.ui.unit.IntSize.Companion Companion;
   }
 
   public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
     method public static inline operator long times-impl(long $this, int other);
     method public static String toString-impl(long $this);
     method public static inline operator long unaryMinus-impl(long $this);
-    field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+    field public static final androidx.ui.unit.TextUnit.Companion Companion;
   }
 
   public static final class TextUnit.Companion {
@@ -462,6 +464,8 @@
   }
 
   public enum TextUnitType {
+    method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.unit.TextUnitType[] values();
     enum_constant public static final androidx.ui.unit.TextUnitType Em;
     enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
     enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -476,7 +480,7 @@
     method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
     method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
     method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
-    field public static final androidx.ui.unit.Uptime.Companion! Companion;
+    field public static final androidx.ui.unit.Uptime.Companion Companion;
   }
 
   public static final class Uptime.Companion {
@@ -494,7 +498,7 @@
     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;
+    field public static final androidx.ui.unit.Velocity.Companion Companion;
   }
 
   public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/restricted_current.txt b/ui/ui-unit/api/restricted_current.txt
index 82aef00..29c348b 100644
--- a/ui/ui-unit/api/restricted_current.txt
+++ b/ui/ui-unit/api/restricted_current.txt
@@ -17,7 +17,7 @@
     property public final int maxWidth;
     property public final int minHeight;
     property public final int minWidth;
-    field public static final androidx.ui.core.Constraints.Companion! Companion;
+    field public static final androidx.ui.core.Constraints.Companion Companion;
     field public static final int Infinity = 2147483647; // 0x7fffffff
   }
 
@@ -41,6 +41,8 @@
   }
 
   public enum LayoutDirection {
+    method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.core.LayoutDirection[] values();
     enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
     enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
   }
@@ -108,7 +110,7 @@
     method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float 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.Dp.Companion! Companion;
+    field public static final androidx.ui.unit.Dp.Companion Companion;
   }
 
   public static final class Dp.Companion {
@@ -214,7 +216,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
     method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
-    field public static final androidx.ui.unit.Duration.Companion! Companion;
+    field public static final androidx.ui.unit.Duration.Companion Companion;
   }
 
   public static final class Duration.Companion {
@@ -268,7 +270,7 @@
     method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
     property public final int x;
     property public final int y;
-    field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+    field public static final androidx.ui.unit.IntOffset.Companion Companion;
   }
 
   public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
     method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
     property public final int height;
     property public final int width;
-    field public static final androidx.ui.unit.IntSize.Companion! Companion;
+    field public static final androidx.ui.unit.IntSize.Companion Companion;
   }
 
   public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
     method public static inline operator long times-impl(long $this, int other);
     method public static String toString-impl(long $this);
     method public static inline operator long unaryMinus-impl(long $this);
-    field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+    field public static final androidx.ui.unit.TextUnit.Companion Companion;
   }
 
   public static final class TextUnit.Companion {
@@ -462,6 +464,8 @@
   }
 
   public enum TextUnitType {
+    method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.ui.unit.TextUnitType[] values();
     enum_constant public static final androidx.ui.unit.TextUnitType Em;
     enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
     enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -476,7 +480,7 @@
     method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
     method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
     method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
-    field public static final androidx.ui.unit.Uptime.Companion! Companion;
+    field public static final androidx.ui.unit.Uptime.Companion Companion;
   }
 
   public static final class Uptime.Companion {
@@ -494,7 +498,7 @@
     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;
+    field public static final androidx.ui.unit.Velocity.Companion Companion;
   }
 
   public static final class Velocity.Companion {
diff --git a/vectordrawable/vectordrawable-animated/api/api_lint.ignore b/vectordrawable/vectordrawable-animated/api/api_lint.ignore
index 8bbfad4..ffd0fdf 100644
--- a/vectordrawable/vectordrawable-animated/api/api_lint.ignore
+++ b/vectordrawable/vectordrawable-animated/api/api_lint.ignore
@@ -59,7 +59,3 @@
     Missing nullability on parameter `dr` in method `unregisterAnimationCallback`
 MissingNullability: androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat#unregisterAnimationCallback(android.graphics.drawable.Drawable, androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback) parameter #1:
     Missing nullability on parameter `callback` in method `unregisterAnimationCallback`
-
-
-NotCloseable: androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat:
-    Classes that release resources (stop()) should implement AutoClosable and CloseGuard: class androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
diff --git a/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml b/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml
index 9ad6fef..f48b579 100644
--- a/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml
+++ b/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml
@@ -22,5 +22,8 @@
     <application
         android:debuggable="false"
         tools:replace="android:debuggable">
+        <!-- enable profileableByShell for non-intrusive profiling tools -->
+        <!--suppress AndroidElementNotAllowed -->
+        <profileable android:shell="true"/>
     </application>
 </manifest>
diff --git a/work/workmanager/api/2.4.0-rc01.txt b/work/workmanager/api/2.4.0-rc01.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/2.4.0-rc01.txt
+++ b/work/workmanager/api/2.4.0-rc01.txt
@@ -46,7 +46,7 @@
     method public boolean requiresCharging();
     method @RequiresApi(23) public boolean requiresDeviceIdle();
     method public boolean requiresStorageNotLow();
-    field public static final androidx.work.Constraints! NONE;
+    field public static final androidx.work.Constraints NONE;
   }
 
   public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
     method public String![]? getStringArray(String);
     method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
     method public byte[] toByteArray();
-    field public static final androidx.work.Data! EMPTY;
+    field public static final androidx.work.Data EMPTY;
     field public static final int MAX_DATA_BYTES = 10240; // 0x2800
   }
 
diff --git a/work/workmanager/api/api_lint.ignore b/work/workmanager/api/api_lint.ignore
index 444e9d1..8454552 100644
--- a/work/workmanager/api/api_lint.ignore
+++ b/work/workmanager/api/api_lint.ignore
@@ -45,14 +45,10 @@
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.WorkRequest.Builder.keepResultsForAtLeast(long,java.util.concurrent.TimeUnit)
 
 
-MissingNullability: androidx.work.Constraints#NONE:
-    Missing nullability on field `NONE` in class `class androidx.work.Constraints`
 MissingNullability: androidx.work.Constraints.Builder#setTriggerContentMaxDelay(java.time.Duration) parameter #0:
     Missing nullability on parameter `duration` in method `setTriggerContentMaxDelay`
 MissingNullability: androidx.work.Constraints.Builder#setTriggerContentUpdateDelay(java.time.Duration) parameter #0:
     Missing nullability on parameter `duration` in method `setTriggerContentUpdateDelay`
-MissingNullability: androidx.work.Data#EMPTY:
-    Missing nullability on field `EMPTY` in class `class androidx.work.Data`
 
 
 NoByteOrShort: androidx.work.Data#getByte(String, byte):
@@ -61,19 +57,3 @@
     Should avoid odd sized primitives; use `int` instead of `byte` in parameter defaultValue in androidx.work.Data.getByte(String key, byte defaultValue)
 NoByteOrShort: androidx.work.Data.Builder#putByte(String, byte) parameter #1:
     Should avoid odd sized primitives; use `int` instead of `byte` in parameter value in androidx.work.Data.Builder.putByte(String key, byte value)
-
-
-SetterReturnsThis: androidx.work.WorkRequest.Builder#addTag(String):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.addTag(String)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setBackoffCriteria(androidx.work.BackoffPolicy, java.time.Duration):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setBackoffCriteria(androidx.work.BackoffPolicy,java.time.Duration)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setBackoffCriteria(androidx.work.BackoffPolicy, long, java.util.concurrent.TimeUnit):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setBackoffCriteria(androidx.work.BackoffPolicy,long,java.util.concurrent.TimeUnit)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setConstraints(androidx.work.Constraints):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setConstraints(androidx.work.Constraints)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setInitialDelay(java.time.Duration):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setInitialDelay(java.time.Duration)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setInitialDelay(long, java.util.concurrent.TimeUnit):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setInitialDelay(long,java.util.concurrent.TimeUnit)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setInputData(androidx.work.Data):
-    Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setInputData(androidx.work.Data)
diff --git a/work/workmanager/api/current.txt b/work/workmanager/api/current.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/current.txt
+++ b/work/workmanager/api/current.txt
@@ -46,7 +46,7 @@
     method public boolean requiresCharging();
     method @RequiresApi(23) public boolean requiresDeviceIdle();
     method public boolean requiresStorageNotLow();
-    field public static final androidx.work.Constraints! NONE;
+    field public static final androidx.work.Constraints NONE;
   }
 
   public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
     method public String![]? getStringArray(String);
     method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
     method public byte[] toByteArray();
-    field public static final androidx.work.Data! EMPTY;
+    field public static final androidx.work.Data EMPTY;
     field public static final int MAX_DATA_BYTES = 10240; // 0x2800
   }
 
diff --git a/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt b/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt
+++ b/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt
@@ -46,7 +46,7 @@
     method public boolean requiresCharging();
     method @RequiresApi(23) public boolean requiresDeviceIdle();
     method public boolean requiresStorageNotLow();
-    field public static final androidx.work.Constraints! NONE;
+    field public static final androidx.work.Constraints NONE;
   }
 
   public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
     method public String![]? getStringArray(String);
     method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
     method public byte[] toByteArray();
-    field public static final androidx.work.Data! EMPTY;
+    field public static final androidx.work.Data EMPTY;
     field public static final int MAX_DATA_BYTES = 10240; // 0x2800
   }
 
diff --git a/work/workmanager/api/public_plus_experimental_current.txt b/work/workmanager/api/public_plus_experimental_current.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/public_plus_experimental_current.txt
+++ b/work/workmanager/api/public_plus_experimental_current.txt
@@ -46,7 +46,7 @@
     method public boolean requiresCharging();
     method @RequiresApi(23) public boolean requiresDeviceIdle();
     method public boolean requiresStorageNotLow();
-    field public static final androidx.work.Constraints! NONE;
+    field public static final androidx.work.Constraints NONE;
   }
 
   public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
     method public String![]? getStringArray(String);
     method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
     method public byte[] toByteArray();
-    field public static final androidx.work.Data! EMPTY;
+    field public static final androidx.work.Data EMPTY;
     field public static final int MAX_DATA_BYTES = 10240; // 0x2800
   }
 
diff --git a/work/workmanager/api/restricted_2.4.0-rc01.txt b/work/workmanager/api/restricted_2.4.0-rc01.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/restricted_2.4.0-rc01.txt
+++ b/work/workmanager/api/restricted_2.4.0-rc01.txt
@@ -46,7 +46,7 @@
     method public boolean requiresCharging();
     method @RequiresApi(23) public boolean requiresDeviceIdle();
     method public boolean requiresStorageNotLow();
-    field public static final androidx.work.Constraints! NONE;
+    field public static final androidx.work.Constraints NONE;
   }
 
   public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
     method public String![]? getStringArray(String);
     method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
     method public byte[] toByteArray();
-    field public static final androidx.work.Data! EMPTY;
+    field public static final androidx.work.Data EMPTY;
     field public static final int MAX_DATA_BYTES = 10240; // 0x2800
   }
 
diff --git a/work/workmanager/api/restricted_current.txt b/work/workmanager/api/restricted_current.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/restricted_current.txt
+++ b/work/workmanager/api/restricted_current.txt
@@ -46,7 +46,7 @@
     method public boolean requiresCharging();
     method @RequiresApi(23) public boolean requiresDeviceIdle();
     method public boolean requiresStorageNotLow();
-    field public static final androidx.work.Constraints! NONE;
+    field public static final androidx.work.Constraints NONE;
   }
 
   public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
     method public String![]? getStringArray(String);
     method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
     method public byte[] toByteArray();
-    field public static final androidx.work.Data! EMPTY;
+    field public static final androidx.work.Data EMPTY;
     field public static final int MAX_DATA_BYTES = 10240; // 0x2800
   }
 
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
index 54ba57a..8f84b5b 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
@@ -43,7 +43,7 @@
                 // WorkManager has not already been initialized.
                 Logger.get().error(TAG,
                         "Cannot reschedule jobs. WorkManager needs to be initialized via a "
-                                + "ContentProvider#onCreate() or an Application#onCreate().");
+                                + "ContentProvider#onCreate() or an Application#onCreate().", e);
             }
         } else {
             Intent reschedule = CommandHandler.createRescheduleIntent(context);