[go: nahoru, domu]

Introduce RootForTest and hide Owner.

Owner interface is now internal. Any usages in testing are replaced with
RootForTest.

Fix: 174747742
Test: N/A
Relnote: "Owner interface from now on internal."
Change-Id: If8e354bd05ef6227abf5ac0765619332752ca8e1
diff --git a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.kt b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.kt
index e860083..4bac800 100644
--- a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.kt
+++ b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.kt
@@ -24,7 +24,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Recomposer
 import androidx.compose.ui.InternalComposeUiApi
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.platform.ViewRootForTest
 import androidx.compose.ui.platform.WindowRecomposerFactory
 import androidx.compose.ui.platform.WindowRecomposerPolicy
@@ -526,7 +526,7 @@
 
         @SuppressLint("DocumentExceptions")
         override fun sendTextInputCommand(node: SemanticsNode, command: List<EditCommand>) {
-            val owner = node.owner as ViewRootForTest
+            val owner = node.root as ViewRootForTest
 
             @Suppress("DEPRECATION")
             runOnUiThread {
@@ -539,7 +539,7 @@
 
         @SuppressLint("DocumentExceptions")
         override fun sendImeAction(node: SemanticsNode, actionSpecified: ImeAction) {
-            val owner = node.owner as ViewRootForTest
+            val owner = node.root as ViewRootForTest
 
             @Suppress("DEPRECATION")
             runOnUiThread {
@@ -555,7 +555,7 @@
             return androidx.compose.ui.test.junit4.runOnUiThread(action)
         }
 
-        override fun getOwners(): Set<Owner> {
+        override fun getRoots(): Set<RootForTest> {
             // TODO(pavlis): Instead of returning a flatMap, let all consumers handle a tree
             //  structure. In case of multiple AndroidOwners, add a fake root
             waitForIdle()
diff --git a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt
index 6d89edb5..90b1b2ba 100644
--- a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt
+++ b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt
@@ -20,7 +20,7 @@
 import androidx.compose.runtime.ExperimentalComposeApi
 import androidx.compose.runtime.Recomposer
 import androidx.compose.runtime.snapshots.Snapshot
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.platform.DesktopOwner
 import androidx.compose.ui.platform.DesktopOwners
 import androidx.compose.ui.platform.setContent
@@ -207,7 +207,7 @@
             return rule.runOnUiThread(action)
         }
 
-        override fun getOwners(): Set<Owner> {
+        override fun getRoots(): Set<RootForTest> {
             return rule.owners!!.list
         }
 
diff --git a/compose/ui/ui-test/api/current.txt b/compose/ui/ui-test/api/current.txt
index 6641d7a..28ad28a 100644
--- a/compose/ui/ui-test/api/current.txt
+++ b/compose/ui/ui-test/api/current.txt
@@ -316,7 +316,7 @@
 
   @androidx.compose.ui.test.InternalTestApi public interface TestOwner {
     method public void advanceTimeBy(long millis);
-    method public java.util.Set<androidx.compose.ui.node.Owner> getOwners();
+    method public java.util.Set<androidx.compose.ui.node.RootForTest> getRoots();
     method public <T> T! runOnUiThread(kotlin.jvm.functions.Function0<? extends T> action);
     method public void sendImeAction(androidx.compose.ui.semantics.SemanticsNode node, androidx.compose.ui.text.input.ImeAction actionSpecified);
     method public void sendTextInputCommand(androidx.compose.ui.semantics.SemanticsNode node, java.util.List<? extends androidx.compose.ui.text.input.EditCommand> command);
diff --git a/compose/ui/ui-test/api/public_plus_experimental_current.txt b/compose/ui/ui-test/api/public_plus_experimental_current.txt
index 6641d7a..28ad28a 100644
--- a/compose/ui/ui-test/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-test/api/public_plus_experimental_current.txt
@@ -316,7 +316,7 @@
 
   @androidx.compose.ui.test.InternalTestApi public interface TestOwner {
     method public void advanceTimeBy(long millis);
-    method public java.util.Set<androidx.compose.ui.node.Owner> getOwners();
+    method public java.util.Set<androidx.compose.ui.node.RootForTest> getRoots();
     method public <T> T! runOnUiThread(kotlin.jvm.functions.Function0<? extends T> action);
     method public void sendImeAction(androidx.compose.ui.semantics.SemanticsNode node, androidx.compose.ui.text.input.ImeAction actionSpecified);
     method public void sendTextInputCommand(androidx.compose.ui.semantics.SemanticsNode node, java.util.List<? extends androidx.compose.ui.text.input.EditCommand> command);
diff --git a/compose/ui/ui-test/api/restricted_current.txt b/compose/ui/ui-test/api/restricted_current.txt
index 6641d7a..28ad28a 100644
--- a/compose/ui/ui-test/api/restricted_current.txt
+++ b/compose/ui/ui-test/api/restricted_current.txt
@@ -316,7 +316,7 @@
 
   @androidx.compose.ui.test.InternalTestApi public interface TestOwner {
     method public void advanceTimeBy(long millis);
-    method public java.util.Set<androidx.compose.ui.node.Owner> getOwners();
+    method public java.util.Set<androidx.compose.ui.node.RootForTest> getRoots();
     method public <T> T! runOnUiThread(kotlin.jvm.functions.Function0<? extends T> action);
     method public void sendImeAction(androidx.compose.ui.semantics.SemanticsNode node, androidx.compose.ui.text.input.ImeAction actionSpecified);
     method public void sendTextInputCommand(androidx.compose.ui.semantics.SemanticsNode node, java.util.List<? extends androidx.compose.ui.text.input.EditCommand> command);
diff --git a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidAssertions.kt b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidAssertions.kt
index 47c42c1..f96f634 100644
--- a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidAssertions.kt
+++ b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidAssertions.kt
@@ -37,7 +37,7 @@
         return false
     }
 
-    (node.owner as? ViewRootForTest)?.let {
+    (node.root as? ViewRootForTest)?.let {
         if (!ViewMatchers.isDisplayed().matches(it.view)) {
             return false
         }
@@ -53,7 +53,7 @@
 }
 
 internal actual fun SemanticsNode.clippedNodeBoundsInWindow(): Rect {
-    val composeView = (owner as ViewRootForTest).view
+    val composeView = (root as ViewRootForTest).view
     val rootLocationInWindow = intArrayOf(0, 0).let {
         composeView.getLocationInWindow(it)
         Offset(it[0].toFloat(), it[1].toFloat())
@@ -62,7 +62,7 @@
 }
 
 internal actual fun SemanticsNode.isInScreenBounds(): Boolean {
-    val composeView = (owner as ViewRootForTest).view
+    val composeView = (root as ViewRootForTest).view
 
     // Window relative bounds of our node
     val nodeBoundsInWindow = clippedNodeBoundsInWindow()
diff --git a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidImageHelpers.kt b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidImageHelpers.kt
index e9de46c..7c82733 100644
--- a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidImageHelpers.kt
+++ b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidImageHelpers.kt
@@ -53,7 +53,7 @@
         )
     }
 
-    val view = (node.owner as ViewRootForTest).view
+    val view = (node.root as ViewRootForTest).view
 
     // If we are in dialog use its window to capture the bitmap
     val dialogParentNodeMaybe = node.findClosestParentNode(includeSelf = true) {
diff --git a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidInputDispatcher.kt b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidInputDispatcher.kt
index 578cf62..0dde1da 100644
--- a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidInputDispatcher.kt
+++ b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/AndroidInputDispatcher.kt
@@ -27,7 +27,7 @@
 import android.view.MotionEvent.ACTION_UP
 import androidx.compose.runtime.dispatch.AndroidUiDispatcher
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.platform.ViewRootForTest
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
@@ -35,20 +35,23 @@
 import kotlinx.coroutines.withContext
 import kotlin.math.max
 
-internal actual fun createInputDispatcher(testContext: TestContext, owner: Owner): InputDispatcher {
-    require(owner is ViewRootForTest) {
+internal actual fun createInputDispatcher(
+    testContext: TestContext,
+    root: RootForTest
+): InputDispatcher {
+    require(root is ViewRootForTest) {
         "InputDispatcher currently only supports dispatching to ViewRootForTest, not to " +
-            owner::class.java.simpleName
+            root::class.java.simpleName
     }
-    val view = owner.view
-    return AndroidInputDispatcher(testContext, owner) { view.dispatchTouchEvent(it) }
+    val view = root.view
+    return AndroidInputDispatcher(testContext, root) { view.dispatchTouchEvent(it) }
 }
 
 internal class AndroidInputDispatcher(
     private val testContext: TestContext,
-    composeRoot: ViewRootForTest?,
+    root: ViewRootForTest?,
     private val sendEvent: (MotionEvent) -> Unit
-) : InputDispatcher(testContext, composeRoot) {
+) : InputDispatcher(testContext, root) {
 
     private val batchLock = Any()
     // Batched events are generated just-in-time, given the "lateness" of the dispatching (see
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GestureScope.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GestureScope.kt
index 6b35b6d..621627c 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GestureScope.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GestureScope.kt
@@ -101,12 +101,9 @@
             "Can't query SemanticsNode, (Partial)GestureScope has already been disposed"
         }
 
-    // Convenience property
-    private val owner get() = semanticsNode.owner
-
     // TODO(b/133217292): Better error: explain which gesture couldn't be performed
     private var _inputDispatcher: InputDispatcher? =
-        createInputDispatcher(testContext, checkNotNull(owner))
+        createInputDispatcher(testContext, checkNotNull(semanticsNode.root))
     internal val inputDispatcher
         get() = checkNotNull(_inputDispatcher) {
             "Can't send gesture, (Partial)GestureScope has already been disposed"
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/InputDispatcher.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/InputDispatcher.kt
index 8da027d..c3b6dde 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/InputDispatcher.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/InputDispatcher.kt
@@ -17,11 +17,14 @@
 
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.lerp
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import kotlin.math.max
 import kotlin.math.roundToInt
 
-internal expect fun createInputDispatcher(testContext: TestContext, owner: Owner): InputDispatcher
+internal expect fun createInputDispatcher(
+    testContext: TestContext,
+    root: RootForTest
+): InputDispatcher
 
 /**
  * Dispatcher to inject full and partial gestures. An [InputDispatcher] is created at the
@@ -52,7 +55,7 @@
  */
 internal abstract class InputDispatcher(
     private val testContext: TestContext,
-    private val owner: Owner?
+    private val root: RootForTest?
 ) {
     companion object {
         /**
@@ -122,7 +125,7 @@
     protected abstract val now: Long
 
     init {
-        val state = testContext.states.remove(owner)
+        val state = testContext.states.remove(root)
         if (state?.partialGesture != null) {
             nextDownTime = state.nextDownTime
             gestureLateness = state.gestureLateness
@@ -130,9 +133,9 @@
         }
     }
 
-    protected open fun saveState(owner: Owner?) {
-        if (owner != null) {
-            testContext.states[owner] =
+    protected open fun saveState(root: RootForTest?) {
+        if (root != null) {
+            testContext.states[root] =
                 InputDispatcherState(
                     nextDownTime,
                     gestureLateness,
@@ -567,7 +570,7 @@
      * Called when this [InputDispatcher] is about to be discarded, from [GestureScope.dispose].
      */
     fun dispose() {
-        saveState(owner)
+        saveState(root)
         onDispose()
     }
 
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/KeyInputHelpers.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/KeyInputHelpers.kt
index 2e0e7e3..b28a86b 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/KeyInputHelpers.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/KeyInputHelpers.kt
@@ -26,8 +26,8 @@
  */
 fun SemanticsNodeInteraction.performKeyPress(keyEvent: KeyEvent): Boolean {
     val semanticsNode = fetchSemanticsNode("Failed to send key Event (${keyEvent.key})")
-    val owner = semanticsNode.owner
-    requireNotNull(owner) { "Failed to find owner" }
+    val root = semanticsNode.root
+    requireNotNull(root) { "Failed to find owner" }
     @OptIn(InternalTestApi::class)
-    return testContext.testOwner.runOnUiThread { owner.sendKeyEvent(keyEvent) }
+    return testContext.testOwner.runOnUiThread { root.sendKeyEvent(keyEvent) }
 }
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt
index 74a2c6d..06abef4 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt
@@ -248,7 +248,7 @@
     operation: Density.(SemanticsNode) -> R
 ): R {
     val node = fetchSemanticsNode("Failed to retrieve density for the node.")
-    val density = node.owner!!.density
+    val density = node.root!!.density
     return operation.invoke(density, node)
 }
 
@@ -256,7 +256,7 @@
     assertion: Density.(Rect) -> Unit
 ): SemanticsNodeInteraction {
     val node = fetchSemanticsNode("Failed to retrieve bounds of the node.")
-    val density = node.owner!!.density
+    val density = node.root!!.density
 
     assertion.invoke(density, node.unclippedBoundsInRoot)
     return this
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TestOwner.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TestOwner.kt
index 5f0afda..d44f775 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TestOwner.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/TestOwner.kt
@@ -16,7 +16,7 @@
 
 package androidx.compose.ui.test
 
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.semantics.SemanticsNode
 import androidx.compose.ui.semantics.getAllSemanticsNodes
 import androidx.compose.ui.text.input.EditCommand
@@ -48,14 +48,14 @@
     fun <T> runOnUiThread(action: () -> T): T
 
     /**
-     * Collects all [Owner]s from all compose hierarchies.
+     * Collects all [RootForTest]s from all compose hierarchies.
      *
      * This is a blocking call. Returns only after compose is idle.
      *
      * Can crash in case it hits time out. This is not supposed to be handled as it
      * surfaces only in incorrect tests.
      */
-    fun getOwners(): Set<Owner>
+    fun getRoots(): Set<RootForTest>
 
     /**
      * Advances time if and only if this [TestOwner] uses a [MainTestClock]
@@ -74,7 +74,7 @@
  */
 @OptIn(InternalTestApi::class)
 internal fun TestOwner.getAllSemanticsNodes(useUnmergedTree: Boolean): List<SemanticsNode> {
-    return getOwners().flatMap { it.semanticsOwner.getAllSemanticsNodes(useUnmergedTree) }
+    return getRoots().flatMap { it.semanticsOwner.getAllSemanticsNodes(useUnmergedTree) }
 }
 
 @InternalTestApi
@@ -86,10 +86,10 @@
 class TestContext internal constructor(internal val testOwner: TestOwner) {
 
     /**
-     * Stores the [InputDispatcherState] of each [Owner]. The state will be restored in an
+     * Stores the [InputDispatcherState] of each [RootForTest]. The state will be restored in an
      * [InputDispatcher] when it is created for an owner that has a state stored.
      */
-    internal val states = mutableMapOf<Owner, InputDispatcherState>()
+    internal val states = mutableMapOf<RootForTest, InputDispatcherState>()
 
     internal fun getAllSemanticsNodes(mergingEnabled: Boolean) =
         testOwner.getAllSemanticsNodes(mergingEnabled)
diff --git a/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/DesktopInputDispatcher.kt b/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/DesktopInputDispatcher.kt
index 2d1f927..4aaddd3 100644
--- a/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/DesktopInputDispatcher.kt
+++ b/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/DesktopInputDispatcher.kt
@@ -18,17 +18,20 @@
 
 import androidx.compose.ui.input.pointer.PointerId
 import androidx.compose.ui.input.pointer.TestPointerInputEventData
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.platform.DesktopOwner
 
-internal actual fun createInputDispatcher(testContext: TestContext, owner: Owner): InputDispatcher {
-    return DesktopInputDispatcher(testContext, owner as DesktopOwner)
+internal actual fun createInputDispatcher(
+    testContext: TestContext,
+    root: RootForTest
+): InputDispatcher {
+    return DesktopInputDispatcher(testContext, root as DesktopOwner)
 }
 
 internal class DesktopInputDispatcher(
     testContext: TestContext,
-    val owner: DesktopOwner
-) : InputDispatcher(testContext, owner) {
+    val root: DesktopOwner
+) : InputDispatcher(testContext, root) {
     companion object {
         var gesturePointerId = 0L
     }
@@ -86,7 +89,7 @@
                     Thread.sleep(delayMs)
                 }
             }
-            owner.processPointerInput(eventTime, it)
+            root.processPointerInput(eventTime, it)
         }
     }
 
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 90634da..863dbec 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -2086,64 +2086,6 @@
     property public abstract long layerId;
   }
 
-  public interface Owner {
-    method public long calculatePosition-nOcc-ac();
-    method public long calculatePositionInWindow-nOcc-ac();
-    method public androidx.compose.ui.node.OwnedLayer createLayer(kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Canvas,kotlin.Unit> drawBlock, kotlin.jvm.functions.Function0<kotlin.Unit> invalidateParentLayer);
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.autofill.Autofill? getAutofill();
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.autofill.AutofillTree getAutofillTree();
-    method public androidx.compose.ui.platform.ClipboardManager getClipboardManager();
-    method public androidx.compose.ui.unit.Density getDensity();
-    method public androidx.compose.ui.focus.FocusManager getFocusManager();
-    method public androidx.compose.ui.text.font.Font.ResourceLoader getFontLoader();
-    method public androidx.compose.ui.hapticfeedback.HapticFeedback getHapticFeedBack();
-    method public androidx.compose.ui.unit.LayoutDirection getLayoutDirection();
-    method public long getMeasureIteration();
-    method public androidx.compose.ui.node.LayoutNode getRoot();
-    method public androidx.compose.ui.semantics.SemanticsOwner getSemanticsOwner();
-    method public boolean getShowLayoutBounds();
-    method public androidx.compose.ui.node.OwnerSnapshotObserver getSnapshotObserver();
-    method public androidx.compose.ui.text.input.TextInputService getTextInputService();
-    method public androidx.compose.ui.platform.TextToolbar getTextToolbar();
-    method public androidx.compose.ui.platform.ViewConfiguration getViewConfiguration();
-    method public androidx.compose.ui.platform.WindowInfo getWindowInfo();
-    method @Deprecated public default androidx.compose.ui.platform.WindowInfo! getWindowManager();
-    method public void measureAndLayout();
-    method public void onAttach(androidx.compose.ui.node.LayoutNode node);
-    method public void onDetach(androidx.compose.ui.node.LayoutNode node);
-    method public void onLayoutChange(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onRequestMeasure(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onRequestRelayout(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onSemanticsChange();
-    method public boolean requestFocus();
-    method public boolean sendKeyEvent-ZmokQxo(android.view.KeyEvent keyEvent);
-    property @androidx.compose.ui.ExperimentalComposeUiApi public abstract androidx.compose.ui.autofill.Autofill? autofill;
-    property @androidx.compose.ui.ExperimentalComposeUiApi public abstract androidx.compose.ui.autofill.AutofillTree autofillTree;
-    property public abstract androidx.compose.ui.platform.ClipboardManager clipboardManager;
-    property public abstract androidx.compose.ui.unit.Density density;
-    property public abstract androidx.compose.ui.focus.FocusManager focusManager;
-    property public abstract androidx.compose.ui.text.font.Font.ResourceLoader fontLoader;
-    property public abstract androidx.compose.ui.hapticfeedback.HapticFeedback hapticFeedBack;
-    property public abstract androidx.compose.ui.unit.LayoutDirection layoutDirection;
-    property public abstract long measureIteration;
-    property public abstract androidx.compose.ui.node.LayoutNode root;
-    property public abstract androidx.compose.ui.semantics.SemanticsOwner semanticsOwner;
-    property public abstract boolean showLayoutBounds;
-    property public abstract androidx.compose.ui.node.OwnerSnapshotObserver snapshotObserver;
-    property public abstract androidx.compose.ui.text.input.TextInputService textInputService;
-    property public abstract androidx.compose.ui.platform.TextToolbar textToolbar;
-    property public abstract androidx.compose.ui.platform.ViewConfiguration viewConfiguration;
-    property public abstract androidx.compose.ui.platform.WindowInfo windowInfo;
-    property @Deprecated public default androidx.compose.ui.platform.WindowInfo! windowManager;
-    field public static final androidx.compose.ui.node.Owner.Companion Companion;
-  }
-
-  public static final class Owner.Companion {
-    method public boolean getEnableExtraAssertions();
-    method public void setEnableExtraAssertions(boolean p);
-    property public final boolean enableExtraAssertions;
-  }
-
   public interface OwnerScope {
     method public boolean isValid();
     property public abstract boolean isValid;
@@ -2160,6 +2102,16 @@
     property public final T? value;
   }
 
+  public interface RootForTest {
+    method public androidx.compose.ui.unit.Density getDensity();
+    method public androidx.compose.ui.semantics.SemanticsOwner getSemanticsOwner();
+    method public androidx.compose.ui.text.input.TextInputService getTextInputService();
+    method public boolean sendKeyEvent-ZmokQxo(android.view.KeyEvent keyEvent);
+    property public abstract androidx.compose.ui.unit.Density density;
+    property public abstract androidx.compose.ui.semantics.SemanticsOwner semanticsOwner;
+    property public abstract androidx.compose.ui.text.input.TextInputService textInputService;
+  }
+
   public final class UiApplier extends androidx.compose.runtime.AbstractApplier<java.lang.Object> {
     ctor public UiApplier(Object root);
     method public void insertBottomUp(int index, Object instance);
@@ -2401,7 +2353,7 @@
     property public abstract float touchSlop;
   }
 
-  @VisibleForTesting public interface ViewRootForTest extends androidx.compose.ui.node.Owner {
+  @VisibleForTesting public interface ViewRootForTest extends androidx.compose.ui.node.RootForTest {
     method public boolean getHasPendingMeasureOrLayout();
     method public android.view.View getView();
     method public void invalidateDescendants();
@@ -2754,9 +2706,9 @@
     method public int getId();
     method public androidx.compose.ui.layout.LayoutInfo getLayoutInfo();
     method public boolean getMergingEnabled();
-    method public androidx.compose.ui.node.Owner? getOwner();
     method public androidx.compose.ui.semantics.SemanticsNode? getParent();
     method public long getPositionInRoot-F1C5BW0();
+    method public androidx.compose.ui.node.RootForTest? getRoot();
     method public long getSize-YbymL2g();
     method public boolean isRoot();
     property public final androidx.compose.ui.geometry.Rect boundsInRoot;
@@ -2768,9 +2720,9 @@
     property public final boolean isRoot;
     property public final androidx.compose.ui.layout.LayoutInfo layoutInfo;
     property public final boolean mergingEnabled;
-    property public final androidx.compose.ui.node.Owner? owner;
     property public final androidx.compose.ui.semantics.SemanticsNode? parent;
     property public final long positionInRoot;
+    property public final androidx.compose.ui.node.RootForTest? root;
     property public final long size;
   }
 
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index 90634da..863dbec 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -2086,64 +2086,6 @@
     property public abstract long layerId;
   }
 
-  public interface Owner {
-    method public long calculatePosition-nOcc-ac();
-    method public long calculatePositionInWindow-nOcc-ac();
-    method public androidx.compose.ui.node.OwnedLayer createLayer(kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Canvas,kotlin.Unit> drawBlock, kotlin.jvm.functions.Function0<kotlin.Unit> invalidateParentLayer);
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.autofill.Autofill? getAutofill();
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.autofill.AutofillTree getAutofillTree();
-    method public androidx.compose.ui.platform.ClipboardManager getClipboardManager();
-    method public androidx.compose.ui.unit.Density getDensity();
-    method public androidx.compose.ui.focus.FocusManager getFocusManager();
-    method public androidx.compose.ui.text.font.Font.ResourceLoader getFontLoader();
-    method public androidx.compose.ui.hapticfeedback.HapticFeedback getHapticFeedBack();
-    method public androidx.compose.ui.unit.LayoutDirection getLayoutDirection();
-    method public long getMeasureIteration();
-    method public androidx.compose.ui.node.LayoutNode getRoot();
-    method public androidx.compose.ui.semantics.SemanticsOwner getSemanticsOwner();
-    method public boolean getShowLayoutBounds();
-    method public androidx.compose.ui.node.OwnerSnapshotObserver getSnapshotObserver();
-    method public androidx.compose.ui.text.input.TextInputService getTextInputService();
-    method public androidx.compose.ui.platform.TextToolbar getTextToolbar();
-    method public androidx.compose.ui.platform.ViewConfiguration getViewConfiguration();
-    method public androidx.compose.ui.platform.WindowInfo getWindowInfo();
-    method @Deprecated public default androidx.compose.ui.platform.WindowInfo! getWindowManager();
-    method public void measureAndLayout();
-    method public void onAttach(androidx.compose.ui.node.LayoutNode node);
-    method public void onDetach(androidx.compose.ui.node.LayoutNode node);
-    method public void onLayoutChange(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onRequestMeasure(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onRequestRelayout(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onSemanticsChange();
-    method public boolean requestFocus();
-    method public boolean sendKeyEvent-ZmokQxo(android.view.KeyEvent keyEvent);
-    property @androidx.compose.ui.ExperimentalComposeUiApi public abstract androidx.compose.ui.autofill.Autofill? autofill;
-    property @androidx.compose.ui.ExperimentalComposeUiApi public abstract androidx.compose.ui.autofill.AutofillTree autofillTree;
-    property public abstract androidx.compose.ui.platform.ClipboardManager clipboardManager;
-    property public abstract androidx.compose.ui.unit.Density density;
-    property public abstract androidx.compose.ui.focus.FocusManager focusManager;
-    property public abstract androidx.compose.ui.text.font.Font.ResourceLoader fontLoader;
-    property public abstract androidx.compose.ui.hapticfeedback.HapticFeedback hapticFeedBack;
-    property public abstract androidx.compose.ui.unit.LayoutDirection layoutDirection;
-    property public abstract long measureIteration;
-    property public abstract androidx.compose.ui.node.LayoutNode root;
-    property public abstract androidx.compose.ui.semantics.SemanticsOwner semanticsOwner;
-    property public abstract boolean showLayoutBounds;
-    property public abstract androidx.compose.ui.node.OwnerSnapshotObserver snapshotObserver;
-    property public abstract androidx.compose.ui.text.input.TextInputService textInputService;
-    property public abstract androidx.compose.ui.platform.TextToolbar textToolbar;
-    property public abstract androidx.compose.ui.platform.ViewConfiguration viewConfiguration;
-    property public abstract androidx.compose.ui.platform.WindowInfo windowInfo;
-    property @Deprecated public default androidx.compose.ui.platform.WindowInfo! windowManager;
-    field public static final androidx.compose.ui.node.Owner.Companion Companion;
-  }
-
-  public static final class Owner.Companion {
-    method public boolean getEnableExtraAssertions();
-    method public void setEnableExtraAssertions(boolean p);
-    property public final boolean enableExtraAssertions;
-  }
-
   public interface OwnerScope {
     method public boolean isValid();
     property public abstract boolean isValid;
@@ -2160,6 +2102,16 @@
     property public final T? value;
   }
 
+  public interface RootForTest {
+    method public androidx.compose.ui.unit.Density getDensity();
+    method public androidx.compose.ui.semantics.SemanticsOwner getSemanticsOwner();
+    method public androidx.compose.ui.text.input.TextInputService getTextInputService();
+    method public boolean sendKeyEvent-ZmokQxo(android.view.KeyEvent keyEvent);
+    property public abstract androidx.compose.ui.unit.Density density;
+    property public abstract androidx.compose.ui.semantics.SemanticsOwner semanticsOwner;
+    property public abstract androidx.compose.ui.text.input.TextInputService textInputService;
+  }
+
   public final class UiApplier extends androidx.compose.runtime.AbstractApplier<java.lang.Object> {
     ctor public UiApplier(Object root);
     method public void insertBottomUp(int index, Object instance);
@@ -2401,7 +2353,7 @@
     property public abstract float touchSlop;
   }
 
-  @VisibleForTesting public interface ViewRootForTest extends androidx.compose.ui.node.Owner {
+  @VisibleForTesting public interface ViewRootForTest extends androidx.compose.ui.node.RootForTest {
     method public boolean getHasPendingMeasureOrLayout();
     method public android.view.View getView();
     method public void invalidateDescendants();
@@ -2754,9 +2706,9 @@
     method public int getId();
     method public androidx.compose.ui.layout.LayoutInfo getLayoutInfo();
     method public boolean getMergingEnabled();
-    method public androidx.compose.ui.node.Owner? getOwner();
     method public androidx.compose.ui.semantics.SemanticsNode? getParent();
     method public long getPositionInRoot-F1C5BW0();
+    method public androidx.compose.ui.node.RootForTest? getRoot();
     method public long getSize-YbymL2g();
     method public boolean isRoot();
     property public final androidx.compose.ui.geometry.Rect boundsInRoot;
@@ -2768,9 +2720,9 @@
     property public final boolean isRoot;
     property public final androidx.compose.ui.layout.LayoutInfo layoutInfo;
     property public final boolean mergingEnabled;
-    property public final androidx.compose.ui.node.Owner? owner;
     property public final androidx.compose.ui.semantics.SemanticsNode? parent;
     property public final long positionInRoot;
+    property public final androidx.compose.ui.node.RootForTest? root;
     property public final long size;
   }
 
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index e6be08b..9ba676f 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -2148,64 +2148,6 @@
     property public abstract long layerId;
   }
 
-  public interface Owner {
-    method public long calculatePosition-nOcc-ac();
-    method public long calculatePositionInWindow-nOcc-ac();
-    method public androidx.compose.ui.node.OwnedLayer createLayer(kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Canvas,kotlin.Unit> drawBlock, kotlin.jvm.functions.Function0<kotlin.Unit> invalidateParentLayer);
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.autofill.Autofill? getAutofill();
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.autofill.AutofillTree getAutofillTree();
-    method public androidx.compose.ui.platform.ClipboardManager getClipboardManager();
-    method public androidx.compose.ui.unit.Density getDensity();
-    method public androidx.compose.ui.focus.FocusManager getFocusManager();
-    method public androidx.compose.ui.text.font.Font.ResourceLoader getFontLoader();
-    method public androidx.compose.ui.hapticfeedback.HapticFeedback getHapticFeedBack();
-    method public androidx.compose.ui.unit.LayoutDirection getLayoutDirection();
-    method public long getMeasureIteration();
-    method public androidx.compose.ui.node.LayoutNode getRoot();
-    method public androidx.compose.ui.semantics.SemanticsOwner getSemanticsOwner();
-    method public boolean getShowLayoutBounds();
-    method public androidx.compose.ui.node.OwnerSnapshotObserver getSnapshotObserver();
-    method public androidx.compose.ui.text.input.TextInputService getTextInputService();
-    method public androidx.compose.ui.platform.TextToolbar getTextToolbar();
-    method public androidx.compose.ui.platform.ViewConfiguration getViewConfiguration();
-    method public androidx.compose.ui.platform.WindowInfo getWindowInfo();
-    method @Deprecated public default androidx.compose.ui.platform.WindowInfo! getWindowManager();
-    method public void measureAndLayout();
-    method public void onAttach(androidx.compose.ui.node.LayoutNode node);
-    method public void onDetach(androidx.compose.ui.node.LayoutNode node);
-    method public void onLayoutChange(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onRequestMeasure(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onRequestRelayout(androidx.compose.ui.node.LayoutNode layoutNode);
-    method public void onSemanticsChange();
-    method public boolean requestFocus();
-    method public boolean sendKeyEvent-ZmokQxo(android.view.KeyEvent keyEvent);
-    property @androidx.compose.ui.ExperimentalComposeUiApi public abstract androidx.compose.ui.autofill.Autofill? autofill;
-    property @androidx.compose.ui.ExperimentalComposeUiApi public abstract androidx.compose.ui.autofill.AutofillTree autofillTree;
-    property public abstract androidx.compose.ui.platform.ClipboardManager clipboardManager;
-    property public abstract androidx.compose.ui.unit.Density density;
-    property public abstract androidx.compose.ui.focus.FocusManager focusManager;
-    property public abstract androidx.compose.ui.text.font.Font.ResourceLoader fontLoader;
-    property public abstract androidx.compose.ui.hapticfeedback.HapticFeedback hapticFeedBack;
-    property public abstract androidx.compose.ui.unit.LayoutDirection layoutDirection;
-    property public abstract long measureIteration;
-    property public abstract androidx.compose.ui.node.LayoutNode root;
-    property public abstract androidx.compose.ui.semantics.SemanticsOwner semanticsOwner;
-    property public abstract boolean showLayoutBounds;
-    property public abstract androidx.compose.ui.node.OwnerSnapshotObserver snapshotObserver;
-    property public abstract androidx.compose.ui.text.input.TextInputService textInputService;
-    property public abstract androidx.compose.ui.platform.TextToolbar textToolbar;
-    property public abstract androidx.compose.ui.platform.ViewConfiguration viewConfiguration;
-    property public abstract androidx.compose.ui.platform.WindowInfo windowInfo;
-    property @Deprecated public default androidx.compose.ui.platform.WindowInfo! windowManager;
-    field public static final androidx.compose.ui.node.Owner.Companion Companion;
-  }
-
-  public static final class Owner.Companion {
-    method public boolean getEnableExtraAssertions();
-    method public void setEnableExtraAssertions(boolean p);
-    property public final boolean enableExtraAssertions;
-  }
-
   public interface OwnerScope {
     method public boolean isValid();
     property public abstract boolean isValid;
@@ -2222,6 +2164,16 @@
     property public final T? value;
   }
 
+  public interface RootForTest {
+    method public androidx.compose.ui.unit.Density getDensity();
+    method public androidx.compose.ui.semantics.SemanticsOwner getSemanticsOwner();
+    method public androidx.compose.ui.text.input.TextInputService getTextInputService();
+    method public boolean sendKeyEvent-ZmokQxo(android.view.KeyEvent keyEvent);
+    property public abstract androidx.compose.ui.unit.Density density;
+    property public abstract androidx.compose.ui.semantics.SemanticsOwner semanticsOwner;
+    property public abstract androidx.compose.ui.text.input.TextInputService textInputService;
+  }
+
   public final class UiApplier extends androidx.compose.runtime.AbstractApplier<java.lang.Object> {
     ctor public UiApplier(Object root);
     method public void insertBottomUp(int index, Object instance);
@@ -2463,7 +2415,7 @@
     property public abstract float touchSlop;
   }
 
-  @VisibleForTesting public interface ViewRootForTest extends androidx.compose.ui.node.Owner {
+  @VisibleForTesting public interface ViewRootForTest extends androidx.compose.ui.node.RootForTest {
     method public boolean getHasPendingMeasureOrLayout();
     method public android.view.View getView();
     method public void invalidateDescendants();
@@ -2816,9 +2768,9 @@
     method public int getId();
     method public androidx.compose.ui.layout.LayoutInfo getLayoutInfo();
     method public boolean getMergingEnabled();
-    method public androidx.compose.ui.node.Owner? getOwner();
     method public androidx.compose.ui.semantics.SemanticsNode? getParent();
     method public long getPositionInRoot-F1C5BW0();
+    method public androidx.compose.ui.node.RootForTest? getRoot();
     method public long getSize-YbymL2g();
     method public boolean isRoot();
     property public final androidx.compose.ui.geometry.Rect boundsInRoot;
@@ -2830,9 +2782,9 @@
     property public final boolean isRoot;
     property public final androidx.compose.ui.layout.LayoutInfo layoutInfo;
     property public final boolean mergingEnabled;
-    property public final androidx.compose.ui.node.Owner? owner;
     property public final androidx.compose.ui.semantics.SemanticsNode? parent;
     property public final long positionInRoot;
+    property public final androidx.compose.ui.node.RootForTest? root;
     property public final long size;
   }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
index 9538232..c28b85c 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
@@ -24,7 +24,6 @@
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Canvas
 import androidx.compose.ui.hapticfeedback.HapticFeedback
-import androidx.compose.ui.input.key.KeyEvent
 import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
@@ -34,11 +33,11 @@
 import androidx.compose.ui.node.OwnedLayer
 import androidx.compose.ui.node.Owner
 import androidx.compose.ui.node.OwnerSnapshotObserver
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.platform.ClipboardManager
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.input.TextInputService
 import androidx.compose.ui.unit.Constraints
@@ -3037,9 +3036,10 @@
     override fun calculatePositionInWindow(): IntOffset = position
 
     override fun requestFocus(): Boolean = false
-    override fun sendKeyEvent(keyEvent: KeyEvent): Boolean = false
     override val root: LayoutNode
         get() = targetRoot
+    override val rootForTest: RootForTest
+        get() = TODO("Not yet implemented")
     override val hapticFeedBack: HapticFeedback
         get() = TODO("Not yet implemented")
     override val clipboardManager: ClipboardManager
@@ -3052,8 +3052,6 @@
         get() = null
     override val density: Density
         get() = Density(1f)
-    override val semanticsOwner: SemanticsOwner
-        get() = TODO("Not yet implemented")
     override val textInputService: TextInputService
         get() = TODO("Not yet implemented")
     override val focusManager: FocusManager
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
index dcdc42e..0a89378 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/DialogSecureFlagTest.kt
@@ -124,7 +124,7 @@
     private fun isSecureFlagEnabledForDialog(): Boolean {
         val owner = rule
             .onNode(isDialog())
-            .fetchSemanticsNode("").owner as View
+            .fetchSemanticsNode("").root as View
         return (owner.rootView.layoutParams as WindowManager.LayoutParams).flags and
             WindowManager.LayoutParams.FLAG_SECURE != 0
     }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.kt
index da1cd3d..2ace3e0 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.kt
@@ -64,6 +64,7 @@
 import androidx.compose.ui.node.OwnedLayer
 import androidx.compose.ui.node.Owner
 import androidx.compose.ui.node.OwnerSnapshotObserver
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.semantics.SemanticsModifierCore
 import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.text.InternalTextApi
@@ -130,6 +131,8 @@
             .then(keyInputModifier)
     }
 
+    override val rootForTest: RootForTest = this
+
     override val semanticsOwner: SemanticsOwner = SemanticsOwner(root)
     private val accessibilityDelegate = AndroidComposeViewAccessibilityDelegateCompat(this)
 
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewRootForTest.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewRootForTest.kt
index 461e12a..77445b1 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewRootForTest.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewRootForTest.kt
@@ -18,15 +18,14 @@
 
 import android.view.View
 import androidx.annotation.VisibleForTesting
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 
 /**
  * The marker interface to be implemented by the [View] backing the composition.
  * To be used in tests.
  */
 @VisibleForTesting
-// TODO(b/174747742) Introduce RootForTest and extend it instead of Owner
-interface ViewRootForTest : Owner {
+interface ViewRootForTest : RootForTest {
 
     /**
      * The view backing this Owner.
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
index 9ec0253..64f47eb 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
@@ -21,12 +21,10 @@
 import androidx.compose.ui.focus.FocusManager
 import androidx.compose.ui.graphics.Canvas
 import androidx.compose.ui.hapticfeedback.HapticFeedback
-import androidx.compose.ui.input.key.KeyEvent
 import androidx.compose.ui.platform.ClipboardManager
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.input.TextInputService
 import androidx.compose.ui.unit.Density
@@ -38,13 +36,15 @@
  * to Android [views][android.view.View] and all layout, draw, input, and accessibility is hooked
  * through them.
  */
-interface Owner {
+internal interface Owner {
 
     /**
      * The root layout node in the component tree.
      */
     val root: LayoutNode
 
+    val rootForTest: RootForTest
+
     /**
      * Provide haptic feedback to the user. Use the Android version of haptic feedback.
      */
@@ -79,8 +79,6 @@
 
     val density: Density
 
-    val semanticsOwner: SemanticsOwner
-
     val textInputService: TextInputService
 
     /**
@@ -158,13 +156,6 @@
     fun requestFocus(): Boolean
 
     /**
-     * Send this [KeyEvent] to the focused component in this [Owner].
-     *
-     * @return true if the event was consumed. False otherwise.
-     */
-    fun sendKeyEvent(keyEvent: KeyEvent): Boolean
-
-    /**
      * Iterates through all LayoutNodes that have requested layout and measures and lays them out
      */
     fun measureAndLayout()
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RootForTest.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RootForTest.kt
new file mode 100644
index 0000000..cd72eb2
--- /dev/null
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RootForTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 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.ui.node
+
+import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.semantics.SemanticsOwner
+import androidx.compose.ui.text.input.TextInputService
+import androidx.compose.ui.unit.Density
+
+/**
+ * The marker interface to be implemented by the root backing the composition.
+ * To be used in tests.
+ */
+interface RootForTest {
+    /**
+     * Current device density.
+     */
+    val density: Density
+
+    /**
+     * Semantics owner for this root. Manages all the semantics nodes.
+     */
+    val semanticsOwner: SemanticsOwner
+
+    /**
+     * The service handling text input.
+     */
+    val textInputService: TextInputService
+
+    /**
+     * Send this [KeyEvent] to the focused component in this [Owner].
+     *
+     * @return true if the event was consumed. False otherwise.
+     */
+    fun sendKeyEvent(keyEvent: KeyEvent): Boolean
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
index 7b5b0f3..87b4899b2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
@@ -26,7 +26,7 @@
 import androidx.compose.ui.layout.globalPosition
 import androidx.compose.ui.node.LayoutNode
 import androidx.compose.ui.node.LayoutNodeWrapper
-import androidx.compose.ui.node.Owner
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.util.fastForEach
 
@@ -73,10 +73,9 @@
     val layoutInfo: LayoutInfo = layoutNodeWrapper.layoutNode
 
     /**
-     * The [Owner] this node is attached to.
+     * The [root][RootForTest] this node is attached to.
      */
-    // TODO(b/174747742) Stop using Owner in tests and use RootForTest instead
-    val owner: Owner? get() = layoutNode.owner
+    val root: RootForTest? get() = layoutNode.owner?.rootForTest
 
     /**
      * The [LayoutNode] that this is associated with.
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt
index 1a72190..8e9fbd0 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwner.kt
@@ -46,6 +46,7 @@
 import androidx.compose.ui.node.MeasureAndLayoutDelegate
 import androidx.compose.ui.node.Owner
 import androidx.compose.ui.node.OwnerSnapshotObserver
+import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.semantics.SemanticsModifierCore
 import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.text.input.TextInputService
@@ -64,7 +65,7 @@
 class DesktopOwner(
     val container: DesktopOwners,
     density: Density = Density(1f, 1f)
-) : Owner {
+) : Owner, RootForTest {
     internal var size by mutableStateOf(IntSize(0, 0))
 
     override var density by mutableStateOf(density)
@@ -97,6 +98,8 @@
             .then(keyInputModifier)
     }
 
+    override val rootForTest = this
+
     override val snapshotObserver = OwnerSnapshotObserver { command ->
         command()
     }
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index 09dfdc4..b262eeb 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -30,7 +30,6 @@
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.hapticfeedback.HapticFeedback
-import androidx.compose.ui.input.key.KeyEvent
 import androidx.compose.ui.input.pointer.PointerInputFilter
 import androidx.compose.ui.input.pointer.PointerInputModifier
 import androidx.compose.ui.layout.LayoutModifier
@@ -44,7 +43,6 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
-import androidx.compose.ui.semantics.SemanticsOwner
 import androidx.compose.ui.text.font.Font
 import androidx.compose.ui.text.input.TextInputService
 import androidx.compose.ui.unit.Constraints
@@ -1720,6 +1718,8 @@
     val >
     var layoutChangeCount = 0
 
+    override val rootForTest: RootForTest
+        get() = TODO("Not yet implemented")
     override val hapticFeedBack: HapticFeedback
         get() = TODO("Not yet implemented")
     override val clipboardManager: ClipboardManager
@@ -1734,8 +1734,6 @@
         get() = TODO("Not yet implemented")
     override val density: Density
         get() = Density(1f)
-    override val semanticsOwner: SemanticsOwner
-        get() = TODO("Not yet implemented")
     override val textInputService: TextInputService
         get() = TODO("Not yet implemented")
     override val focusManager: FocusManager
@@ -1771,8 +1769,6 @@
 
     override fun requestFocus(): Boolean = false
 
-    override fun sendKeyEvent(keyEvent: KeyEvent): Boolean = false
-
     override fun measureAndLayout() {
     }