[go: nahoru, domu]

Merge "Update nav compose to navigation-runtime 2.3.1" into androidx-master-dev
diff --git a/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt b/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
index 7042a64..f88c50d 100644
--- a/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
@@ -46,9 +46,7 @@
     "createProjectZip",
     "desugarPublicDebugFileDependencies",
     "desugarTipOfTreeDebugFileDependencies",
-    "distPublicDokkaDocs",
-    "dokkaJavaPublicDocs",
-    "dokkaKotlinPublicDocs",
+    "dokkaKotlinDocs",
     "externalNativeBuildDebug",
     "externalNativeBuildRelease",
     "generateJsonModelDebug",
@@ -89,10 +87,10 @@
     "stripArchiveForPartialDejetification",
     "transformClassesWithDexBuilderForPublicDebug",
     "transformClassesWithDexBuilderForTipOfTreeDebug",
-    "unzipDokkaPublicDocsDeps",
     "verifyDependencyVersions",
     "zipEcFiles",
     "zipTestConfigsWithApks",
+    "zipDokkaDocs",
 
     ":camera:integration-tests:camera-testapp-core:mergeLibDexDebug",
     ":camera:integration-tests:camera-testapp-core:packageDebug",
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
index 987a8af..5b24ca5 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
@@ -118,4 +118,25 @@
             ContentValues()
         )
     }
+
+    @UiThreadTest
+    @Test
+    public fun analysisIsEnabledByDefault() {
+        assertThat(controller.isImageAnalysisEnabled).isTrue()
+    }
+
+    @UiThreadTest
+    @Test
+    public fun captureIsEnabledByDefault() {
+        assertThat(controller.isImageCaptureEnabled).isTrue()
+    }
+
+    @UiThreadTest
+    @Test
+    public fun disableAnalysisCaptureEnableVideo() {
+        controller.setEnabledUseCases(CameraController.VIDEO_CAPTURE)
+        assertThat(controller.isImageCaptureEnabled).isFalse()
+        assertThat(controller.isImageAnalysisEnabled).isFalse()
+        assertThat(controller.isVideoCaptureEnabled).isTrue()
+    }
 }
\ No newline at end of file
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
index 6c64e5f..a88f629 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
@@ -103,8 +103,28 @@
     private static final float AF_SIZE = 1.0f / 6.0f;
     private static final float AE_SIZE = AF_SIZE * 1.5f;
 
+    /**
+     * Bitmask option to enable {@link android.media.Image}. In {@link #setEnabledUseCases}, if
+     * (enabledUseCases & IMAGE_CAPTURE) != 0, then controller will enable image capture features.
+     */
+    public static int IMAGE_CAPTURE = 0b1;
+    /**
+     * Bitmask option to enable {@link ImageAnalysis}. In {@link #setEnabledUseCases}, if
+     * (enabledUseCases & IMAGE_ANALYSIS) != 0, then controller will enable image analysis features.
+     */
+    public static int IMAGE_ANALYSIS = 0b10;
+    /**
+     * Bitmask option to enable video capture use case. In {@link #setEnabledUseCases}, if
+     * (enabledUseCases & VIDEO_CAPTURE) != 0, then controller will enable video capture features.
+     */
+    @ExperimentalVideo
+    public static int VIDEO_CAPTURE = 0b100;
+
     CameraSelector mCameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
 
+    // By default, ImageCapture and ImageAnalysis are enabled. VideoCapture is disabled.
+    private int mEnabledUseCases = IMAGE_CAPTURE | IMAGE_ANALYSIS;
+
     // CameraController and PreviewView hold reference to each other. The 2-way link is managed
     // by PreviewView.
     // Synthetic access
@@ -117,12 +137,6 @@
     @NonNull
     final ImageCapture mImageCapture;
 
-    // ImageCapture is enabled by default.
-    private boolean mImageCaptureEnabled = true;
-
-    // ImageAnalysis is enabled by default.
-    private boolean mImageAnalysisEnabled = true;
-
     @Nullable
     private Executor mAnalysisExecutor;
 
@@ -137,9 +151,6 @@
     @NonNull
     final VideoCapture mVideoCapture;
 
-    // VideoCapture is disabled by default.
-    private boolean mVideoCaptureEnabled = false;
-
     // Synthetic access
     @SuppressWarnings("WeakerAccess")
     @NonNull
@@ -258,6 +269,78 @@
         return mCamera != null;
     }
 
+    /**
+     * Enables or disables use cases.
+     *
+     * <p> Use cases need to be enabled before they can be used. By default, {@link #IMAGE_CAPTURE}
+     * and {@link #IMAGE_ANALYSIS} are enabled, and {@link #VIDEO_CAPTURE} is disabled. This is
+     * necessary because {@link #VIDEO_CAPTURE} is an experimental feature that might not work
+     * with other use cases, especially on lower end devices. When that happens, this method will
+     * fail with an {@link IllegalStateException}.
+     *
+     * <p> To make sure {@link #VIDEO_CAPTURE} works, {@link #IMAGE_CAPTURE} and
+     * {@link #IMAGE_ANALYSIS} needs to be disabled when enabling {@link #VIDEO_CAPTURE}. For
+     * example:
+     *
+     * <pre><code>
+     * // By default, image capture is enabled. Taking picture works.
+     * controller.takePicture(...);
+     *
+     * // Switch to video capture to shoot video.
+     * controller.setEnabledUseCases(VIDEO_CAPTURE);
+     * controller.startRecording(...);
+     * controller.stopRecording(...);
+     *
+     * // Switch back to image capture and image analysis before taking another picture.
+     * controller.setEnabledUseCases(IMAGE_CAPTURE|IMAGE_ANALYSIS);
+     * controller.takePicture(...);
+     *
+     * </code></pre>
+     *
+     * @param enabledUseCases one or more of the following use cases, bitwise-OR-ed together:
+     *                        {@link #IMAGE_CAPTURE}, {@link #IMAGE_ANALYSIS} and/or
+     *                        {@link #VIDEO_CAPTURE}.
+     * @throws IllegalStateException If the current camera selector is unable to resolve a
+     *                               camera to be used for the enabled use cases.
+     * @see UseCase
+     * @see ImageCapture
+     * @see ImageAnalysis
+     */
+    @UseExperimental(markerClass = ExperimentalVideo.class)
+    public void setEnabledUseCases(int enabledUseCases) {
+        if (enabledUseCases == mEnabledUseCases) {
+            return;
+        }
+        int oldEnabledUseCases = mEnabledUseCases;
+        mEnabledUseCases = enabledUseCases;
+        if (!isVideoCaptureEnabled()) {
+            stopRecording();
+        }
+        startCameraAndTrackStates(() -> mEnabledUseCases = oldEnabledUseCases);
+    }
+
+    /**
+     * Checks if the given use case mask is enabled.
+     *
+     * @param useCaseMask One of the {@link #IMAGE_CAPTURE}, {@link #IMAGE_ANALYSIS} or
+     *                    {@link #VIDEO_CAPTURE}
+     * @return true if the use case is enabled.
+     */
+    private boolean isUseCaseEnabled(int useCaseMask) {
+        return (mEnabledUseCases & useCaseMask) != 0;
+    }
+
+    /**
+     * Same as {@link #isVideoCaptureEnabled()}.
+     *
+     * <p> This wrapper method is to workaround the limitation that currently only one
+     * {@link UseExperimental} mark class is allowed per method.
+     */
+    @UseExperimental(markerClass = ExperimentalVideo.class)
+    private boolean isVideoCaptureEnabledInternal() {
+        return isVideoCaptureEnabled();
+    }
+
     // ------------------
     // Preview use case.
     // ------------------
@@ -331,28 +414,7 @@
     @MainThread
     public boolean isImageCaptureEnabled() {
         Threads.checkMainThread();
-        return mImageCaptureEnabled;
-    }
-
-    /**
-     * Enables or disables {@link ImageCapture}.
-     *
-     * <p> {@link ImageCapture} might not work with video capture depending on device
-     * limitations. In that case, the method will fail with {@link IllegalStateException}.
-     *
-     * @throws IllegalArgumentException If the current camera selector is unable to resolve a
-     *                                  camera to be used for the enabled use cases.
-     * @see ImageCapture
-     */
-    @MainThread
-    public void setImageCaptureEnabled(boolean imageCaptureEnabled) {
-        Threads.checkMainThread();
-        if (mImageCaptureEnabled == imageCaptureEnabled) {
-            return;
-        }
-        boolean oldImageCaptureEnabled = mImageCaptureEnabled;
-        mImageCaptureEnabled = imageCaptureEnabled;
-        startCameraAndTrackStates(() -> mImageAnalysisEnabled = oldImageCaptureEnabled);
+        return isUseCaseEnabled(IMAGE_CAPTURE);
     }
 
     /**
@@ -405,7 +467,7 @@
             @NonNull ImageCapture.OnImageSavedCallback imageSavedCallback) {
         Threads.checkMainThread();
         Preconditions.checkState(isCameraInitialized(), CAMERA_NOT_INITIALIZED);
-        Preconditions.checkState(mImageCaptureEnabled, IMAGE_CAPTURE_DISABLED);
+        Preconditions.checkState(isImageCaptureEnabled(), IMAGE_CAPTURE_DISABLED);
 
         updateMirroringFlagInOutputFileOptions(outputFileOptions);
         mImageCapture.takePicture(outputFileOptions, executor, imageSavedCallback);
@@ -445,7 +507,7 @@
             @NonNull ImageCapture.OnImageCapturedCallback callback) {
         Threads.checkMainThread();
         Preconditions.checkState(isCameraInitialized(), CAMERA_NOT_INITIALIZED);
-        Preconditions.checkState(mImageCaptureEnabled, IMAGE_CAPTURE_DISABLED);
+        Preconditions.checkState(isImageCaptureEnabled(), IMAGE_CAPTURE_DISABLED);
 
         mImageCapture.takePicture(executor, callback);
     }
@@ -462,28 +524,7 @@
     @MainThread
     public boolean isImageAnalysisEnabled() {
         Threads.checkMainThread();
-        return mImageAnalysisEnabled;
-    }
-
-    /**
-     * Enables or disables {@link ImageAnalysis} use case.
-     *
-     * <p> {@link ImageAnalysis} might not work with video capture depending on device
-     * limitations. In that case, the method will fail with {@link IllegalStateException}.
-     *
-     * @throws IllegalStateException If the current camera selector is unable to resolve a
-     *                               camera to be used for the enabled use cases.
-     * @see ImageAnalysis
-     */
-    @MainThread
-    public void setImageAnalysisEnabled(boolean imageAnalysisEnabled) {
-        Threads.checkMainThread();
-        if (mImageAnalysisEnabled == imageAnalysisEnabled) {
-            return;
-        }
-        boolean oldImageAnalysisEnabled = mImageAnalysisEnabled;
-        mImageAnalysisEnabled = imageAnalysisEnabled;
-        startCameraAndTrackStates(() -> mImageAnalysisEnabled = oldImageAnalysisEnabled);
+        return isUseCaseEnabled(IMAGE_ANALYSIS);
     }
 
     /**
@@ -630,32 +671,7 @@
     @MainThread
     public boolean isVideoCaptureEnabled() {
         Threads.checkMainThread();
-        return mVideoCaptureEnabled;
-    }
-
-    /**
-     * Enables or disables video capture use case.
-     *
-     * <p> Due to hardware limitations, video capture might not work when {@link ImageAnalysis}
-     * and/or {@link ImageCapture} is enabled. In that case, this method will fail with an
-     * {@link IllegalStateException}.
-     *
-     * @throws IllegalStateException If the current camera selector is unable to resolve a
-     *                               camera to be used for the enabled use cases.
-     */
-    @ExperimentalVideo
-    @MainThread
-    public void setVideoCaptureEnabled(boolean videoCaptureEnabled) {
-        Threads.checkMainThread();
-        if (mVideoCaptureEnabled == videoCaptureEnabled) {
-            return;
-        }
-        if (!videoCaptureEnabled) {
-            stopRecording();
-        }
-        boolean oldVideoCaptureEnabled = mVideoCaptureEnabled;
-        mVideoCaptureEnabled = videoCaptureEnabled;
-        startCameraAndTrackStates(() -> mVideoCaptureEnabled = oldVideoCaptureEnabled);
+        return isUseCaseEnabled(VIDEO_CAPTURE);
     }
 
     /**
@@ -671,7 +687,7 @@
             @NonNull Executor executor, final @NonNull OnVideoSavedCallback callback) {
         Threads.checkMainThread();
         Preconditions.checkState(isCameraInitialized(), CAMERA_NOT_INITIALIZED);
-        Preconditions.checkState(mVideoCaptureEnabled, VIDEO_CAPTURE_DISABLED);
+        Preconditions.checkState(isVideoCaptureEnabled(), VIDEO_CAPTURE_DISABLED);
 
         mVideoCapture.startRecording(outputFileOptions.toVideoCaptureOutputFileOptions(), executor,
                 new VideoCapture.OnVideoSavedCallback() {
@@ -1041,19 +1057,19 @@
 
         UseCaseGroup.Builder builder = new UseCaseGroup.Builder().addUseCase(mPreview);
 
-        if (mImageCaptureEnabled) {
+        if (isImageCaptureEnabled()) {
             builder.addUseCase(mImageCapture);
         } else {
             mCameraProvider.unbind(mImageCapture);
         }
 
-        if (mImageAnalysisEnabled) {
+        if (isImageAnalysisEnabled()) {
             builder.addUseCase(mImageAnalysis);
         } else {
             mCameraProvider.unbind(mImageAnalysis);
         }
 
-        if (mVideoCaptureEnabled) {
+        if (isVideoCaptureEnabledInternal()) {
             builder.addUseCase(mVideoCapture);
         } else {
             mCameraProvider.unbind(mVideoCapture);
diff --git a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
index ce10c35..2b5868a 100644
--- a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
+++ b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
@@ -120,9 +120,7 @@
         val fragment = createFragmentScenario().getFragment()
         fragment.assertAnalysisStreaming(true)
 
-        instrumentation.runOnMainSync {
-            fragment.cameraController.isImageAnalysisEnabled = false
-        }
+        onView(withId(R.id.analysis_enabled)).perform(click())
 
         fragment.assertAnalysisStreaming(false)
     }
@@ -132,10 +130,8 @@
         val fragment = createFragmentScenario().getFragment()
         fragment.assertAnalysisStreaming(true)
 
-        instrumentation.runOnMainSync {
-            fragment.cameraController.isImageAnalysisEnabled = false
-            fragment.cameraController.isImageAnalysisEnabled = true
-        }
+        onView(withId(R.id.analysis_enabled)).perform(click())
+        onView(withId(R.id.analysis_enabled)).perform(click())
 
         fragment.assertAnalysisStreaming(true)
     }
@@ -156,7 +152,7 @@
     fun canSetAnalysisImageDepth() {
         // Arrange.
         val fragment = createFragmentScenario().getFragment()
-        var currentDepth: Int = 0
+        var currentDepth = 0
 
         // Act.
         instrumentation.runOnMainSync {
@@ -269,11 +265,11 @@
         thrown.expectMessage("ImageCapture disabled")
         val fragment = createFragmentScenario().getFragment()
         fragment.assertPreviewIsStreaming()
-        instrumentation.runOnMainSync {
-            fragment.cameraController.isImageCaptureEnabled = false
-        }
 
-        // Act & assert.
+        // Act.
+        onView(withId(R.id.capture_enabled)).perform(click())
+
+        // Assert.
         fragment.assertCanTakePicture()
     }
 
@@ -284,10 +280,8 @@
         fragment.assertPreviewIsStreaming()
 
         // Act.
-        instrumentation.runOnMainSync {
-            fragment.cameraController.isImageCaptureEnabled = false
-            fragment.cameraController.isImageCaptureEnabled = true
-        }
+        onView(withId(R.id.capture_enabled)).perform(click())
+        onView(withId(R.id.capture_enabled)).perform(click())
         fragment.assertPreviewIsStreaming()
 
         // Assert.
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
index a7c83db..173165f 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.CompoundButton;
 import android.widget.FrameLayout;
 import android.widget.SeekBar;
 import android.widget.TextView;
@@ -47,6 +48,7 @@
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.FutureCallback;
 import androidx.camera.core.impl.utils.futures.Futures;
+import androidx.camera.view.CameraController;
 import androidx.camera.view.LifecycleCameraController;
 import androidx.camera.view.PreviewView;
 import androidx.camera.view.SensorRotationListener;
@@ -80,6 +82,8 @@
     private Button mFlashMode;
     private ToggleButton mCameraToggle;
     private ExecutorService mExecutorService;
+    private ToggleButton mCaptureEnabledToggle;
+    private ToggleButton mAnalysisEnabledToggle;
     private ToggleButton mVideoEnabledToggle;
     private ToggleButton mPinchToZoomToggle;
     private ToggleButton mTapToFocusToggle;
@@ -164,11 +168,9 @@
                                 : CameraSelector.DEFAULT_FRONT_CAMERA)));
 
         // Image Capture enable switch.
-        ToggleButton captureEnabled = view.findViewById(R.id.capture_enabled);
-        captureEnabled.setOnCheckedChangeListener(
-                (compoundButton, value) -> runSafely(
-                        () -> mCameraController.setImageCaptureEnabled(value)));
-        captureEnabled.setChecked(mCameraController.isImageCaptureEnabled());
+        mCaptureEnabledToggle = view.findViewById(R.id.capture_enabled);
+        mCaptureEnabledToggle.setOnCheckedChangeListener(this::onUseCaseToggled);
+        mCaptureEnabledToggle.setChecked(mCameraController.isImageCaptureEnabled());
 
         // Flash mode for image capture.
         mFlashMode = view.findViewById(R.id.flash_mode);
@@ -212,11 +214,10 @@
                 });
 
         // Set up analysis UI.
-        ToggleButton analysisEnabled = view.findViewById(R.id.analysis_enabled);
-        analysisEnabled.setOnCheckedChangeListener(
-                (compoundButton, value) ->
-                        runSafely(() -> mCameraController.setImageAnalysisEnabled(value)));
-        analysisEnabled.setChecked(mCameraController.isImageAnalysisEnabled());
+        mAnalysisEnabledToggle = view.findViewById(R.id.analysis_enabled);
+        mAnalysisEnabledToggle.setOnCheckedChangeListener(
+                this::onUseCaseToggled);
+        mAnalysisEnabledToggle.setChecked(mCameraController.isImageAnalysisEnabled());
 
         ToggleButton analyzerSet = view.findViewById(R.id.analyzer_set);
         analyzerSet.setOnCheckedChangeListener(
@@ -233,7 +234,7 @@
         mVideoEnabledToggle = view.findViewById(R.id.video_enabled);
         mVideoEnabledToggle.setOnCheckedChangeListener(
                 (compoundButton, checked) -> {
-                    runSafely(() -> mCameraController.setVideoCaptureEnabled(checked));
+                    onUseCaseToggled(compoundButton, checked);
                     updateUiText();
                 });
 
@@ -425,6 +426,26 @@
         }
     }
 
+    @UseExperimental(markerClass = ExperimentalVideo.class)
+    private void onUseCaseToggled(CompoundButton compoundButton, boolean value) {
+        if (mCaptureEnabledToggle == null || mAnalysisEnabledToggle == null
+                || mVideoEnabledToggle == null) {
+            return;
+        }
+        int useCaseEnabledFlags = 0;
+        if (mCaptureEnabledToggle.isChecked()) {
+            useCaseEnabledFlags = useCaseEnabledFlags | CameraController.IMAGE_CAPTURE;
+        }
+        if (mAnalysisEnabledToggle.isChecked()) {
+            useCaseEnabledFlags = useCaseEnabledFlags | CameraController.IMAGE_ANALYSIS;
+        }
+        if (mVideoEnabledToggle.isChecked()) {
+            useCaseEnabledFlags = useCaseEnabledFlags | CameraController.VIDEO_CAPTURE;
+        }
+        final int finalUseCaseEnabledFlags = useCaseEnabledFlags;
+        runSafely(() -> mCameraController.setEnabledUseCases(finalUseCaseEnabledFlags));
+    }
+
     // -----------------
     // For testing
     // -----------------
diff --git a/compose/foundation/foundation-text/api/current.txt b/compose/foundation/foundation-text/api/current.txt
index d699196..5b05f0e 100644
--- a/compose/foundation/foundation-text/api/current.txt
+++ b/compose/foundation/foundation-text/api/current.txt
@@ -2,7 +2,7 @@
 package androidx.compose.foundation.text {
 
   public final class CoreTextFieldKt {
-    method @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void CoreTextField-wQ2hrV0(androidx.compose.ui.text.input.TextFieldValue value, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.ui.text.input.KeyboardType keyboardType, optional androidx.compose.ui.text.input.ImeAction imeAction, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional long cursorColor, optional boolean softWrap, optional int maxLines, optional androidx.compose.ui.text.input.KeyboardOptions keyboardOptions);
+    method @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void CoreTextField-dSfP_Go(androidx.compose.ui.text.input.TextFieldValue value, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional long cursorColor, optional boolean softWrap, optional int maxLines, optional androidx.compose.ui.text.input.KeyboardOptions keyboardOptions);
     method @Deprecated @VisibleForTesting public static void setBlinkingCursorEnabled(boolean p);
   }
 
diff --git a/compose/foundation/foundation-text/api/public_plus_experimental_current.txt b/compose/foundation/foundation-text/api/public_plus_experimental_current.txt
index d699196..5b05f0e 100644
--- a/compose/foundation/foundation-text/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation-text/api/public_plus_experimental_current.txt
@@ -2,7 +2,7 @@
 package androidx.compose.foundation.text {
 
   public final class CoreTextFieldKt {
-    method @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void CoreTextField-wQ2hrV0(androidx.compose.ui.text.input.TextFieldValue value, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.ui.text.input.KeyboardType keyboardType, optional androidx.compose.ui.text.input.ImeAction imeAction, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional long cursorColor, optional boolean softWrap, optional int maxLines, optional androidx.compose.ui.text.input.KeyboardOptions keyboardOptions);
+    method @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void CoreTextField-dSfP_Go(androidx.compose.ui.text.input.TextFieldValue value, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional long cursorColor, optional boolean softWrap, optional int maxLines, optional androidx.compose.ui.text.input.KeyboardOptions keyboardOptions);
     method @Deprecated @VisibleForTesting public static void setBlinkingCursorEnabled(boolean p);
   }
 
diff --git a/compose/foundation/foundation-text/api/restricted_current.txt b/compose/foundation/foundation-text/api/restricted_current.txt
index d699196..5b05f0e 100644
--- a/compose/foundation/foundation-text/api/restricted_current.txt
+++ b/compose/foundation/foundation-text/api/restricted_current.txt
@@ -2,7 +2,7 @@
 package androidx.compose.foundation.text {
 
   public final class CoreTextFieldKt {
-    method @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void CoreTextField-wQ2hrV0(androidx.compose.ui.text.input.TextFieldValue value, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.ui.text.input.KeyboardType keyboardType, optional androidx.compose.ui.text.input.ImeAction imeAction, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional long cursorColor, optional boolean softWrap, optional int maxLines, optional androidx.compose.ui.text.input.KeyboardOptions keyboardOptions);
+    method @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void CoreTextField-dSfP_Go(androidx.compose.ui.text.input.TextFieldValue value, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.SoftwareKeyboardController,kotlin.Unit> onTextInputStarted, optional long cursorColor, optional boolean softWrap, optional int maxLines, optional androidx.compose.ui.text.input.KeyboardOptions keyboardOptions);
     method @Deprecated @VisibleForTesting public static void setBlinkingCursorEnabled(boolean p);
   }
 
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt
index 8e24042..a747bfc 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelection.kt
@@ -23,12 +23,9 @@
 import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.selection.DisableSelection
-import androidx.compose.ui.selection.Selection
 import androidx.compose.ui.selection.SelectionContainer
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
@@ -54,13 +51,9 @@
 
 @Composable
 fun TextDemoSelection() {
-    val selection = remember { mutableStateOf<Selection?>(null) }
     val arabicSentence =
         "\nكلمة شين في قاموس المعاني الفوري مجال البحث مصطلحات المعجم الوسيط ،اللغة"
-    SelectionContainer(
-        selection = selection.value,
-         selection.value = it }
-    ) {
+    SelectionContainer {
         Text(
             style = TextStyle(
                 color = Color(0xFFFF0000),
@@ -100,11 +93,7 @@
 
 @Composable
 fun TextDemoSelectionWithStringInput() {
-    val selection = remember { mutableStateOf<Selection?>(null) }
-    SelectionContainer(
-        selection = selection.value,
-         selection.value = it }
-    ) {
+    SelectionContainer {
         Text(
             text = "$displayText    $displayTextChinese    $displayTextHindi",
             color = Color(0xFFFF0000),
@@ -134,11 +123,7 @@
         Color(0xFFFF0000)
     )
 
-    val selection = remember { mutableStateOf<Selection?>(null) }
-    SelectionContainer(
-        selection = selection.value,
-         selection.value = it }
-    ) {
+    SelectionContainer {
         Column(Modifier.fillMaxHeight()) {
             for (i in 0..2) {
                 Row(Modifier.fillMaxWidth()) {
@@ -163,12 +148,7 @@
     val textSelectable = "This text is selectable."
     val textNotSelectable = "This text is not selectable."
 
-    val selection = remember { mutableStateOf<Selection?>(null) }
-
-    SelectionContainer(
-        selection = selection.value,
-         selection.value = it }
-    ) {
+    SelectionContainer {
         Column(Modifier.fillMaxHeight()) {
             Text(
                 text = textSelectable,
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelectionSample.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelectionSample.kt
index f9f94a8..3674cf1 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelectionSample.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/ComposeTextSelectionSample.kt
@@ -25,11 +25,8 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.preferredSize
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.selection.Selection
 import androidx.compose.ui.selection.SelectionContainer
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
@@ -74,12 +71,8 @@
 
 @Composable
 fun TextSelectionSample() {
-    val selection = remember { mutableStateOf<Selection?>(null) }
     ScrollableColumn {
-        SelectionContainer(
-            selection = selection.value,
-             selection.value = it }
-        ) {
+        SelectionContainer {
             Column(Modifier.padding(12.dp)) {
                 Basics()
                 AddTextElement()
diff --git a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/KeyboardOptionsDemo.kt b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/KeyboardOptionsDemo.kt
index e9b17f2..26f0042 100644
--- a/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/KeyboardOptionsDemo.kt
+++ b/compose/foundation/foundation-text/integration-tests/ui-text-compose-demos/src/main/java/androidx/compose/foundation/text/demos/KeyboardOptionsDemo.kt
@@ -39,62 +39,80 @@
 @OptIn(ExperimentalTextApi::class)
 private class KeyboardOptionsData(
     val keyboardOptions: KeyboardOptions,
-    val keyboardType: KeyboardType,
     val name: String,
-    val imeAction: ImeAction = ImeAction.Unspecified
 )
 
 @OptIn(ExperimentalTextApi::class)
 private val KeyboardOptionsList = listOf(
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(singleLine = true),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            singleLine = true,
+            keyboardType = KeyboardType.Text
+        ),
         name = "singleLine/Text"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(singleLine = false),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            singleLine = false,
+            keyboardType = KeyboardType.Text
+        ),
         name = "multiLine/Text"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(singleLine = true),
-        keyboardType = KeyboardType.Text,
-        imeAction = ImeAction.Search,
+        keyboardOptions = KeyboardOptions(
+            singleLine = true,
+            keyboardType = KeyboardType.Text,
+            imeAction = ImeAction.Search
+        ),
         name = "singleLine/Text/Search"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(singleLine = true),
-        keyboardType = KeyboardType.Number,
+        keyboardOptions = KeyboardOptions(
+            singleLine = true,
+            keyboardType = KeyboardType.Number
+        ),
         name = "singleLine/Number"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(singleLine = false),
-        keyboardType = KeyboardType.Number,
+        keyboardOptions = KeyboardOptions(
+            singleLine = false,
+            keyboardType = KeyboardType.Number
+        ),
         name = "multiLine/Number"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Characters),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            capitalization = KeyboardCapitalization.Characters,
+            keyboardType = KeyboardType.Text
+        ),
         name = "Capitalize Characters"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Words),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            capitalization = KeyboardCapitalization.Words,
+            keyboardType = KeyboardType.Text
+        ),
         name = "Capitalize Words"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            capitalization = KeyboardCapitalization.Sentences,
+            keyboardType = KeyboardType.Text
+        ),
         name = "Capitalize Sentences"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(autoCorrect = true),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            autoCorrect = true,
+            keyboardType = KeyboardType.Text
+        ),
         name = "AutoCorrect On"
     ),
     KeyboardOptionsData(
-        keyboardOptions = KeyboardOptions(autoCorrect = false),
-        keyboardType = KeyboardType.Text,
+        keyboardOptions = KeyboardOptions(
+            autoCorrect = false,
+            keyboardType = KeyboardType.Text
+        ),
         name = "AutoCorrect Off"
     )
 )
@@ -122,8 +140,6 @@
     CoreTextField(
         modifier = demoTextFieldModifiers.defaultMinSizeConstraints(100.dp),
         value = state.value,
-        keyboardType = data.keyboardType,
-        imeAction = data.imeAction,
         keyboardOptions = data.keyboardOptions,
          state.value = it },
         textStyle = TextStyle(fontSize = fontSize8),
diff --git a/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt b/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt
index 31bfb8a..e0ec19b 100644
--- a/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt
+++ b/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextFieldInputServiceIntegrationTest.kt
@@ -69,18 +69,17 @@
         val keyboardOptions = KeyboardOptions(
             singleLine = true,
             capitalization = KeyboardCapitalization.Words,
-            autoCorrect = false
+            autoCorrect = false,
+            keyboardType = KeyboardType.Phone,
+            imeAction = ImeAction.Search
         )
-        val keyboardType = KeyboardType.Phone
-        val imeAction = ImeAction.Search
+
         var focused = false
 
         rule.setContent {
             CoreTextField(
                 value = value,
                 keyboardOptions = keyboardOptions,
-                keyboardType = keyboardType,
-                imeAction = imeAction,
                 modifier = Modifier
                     .testTag(testTag)
                     .focusObserver { focused = it.isFocused },
@@ -95,8 +94,6 @@
 
             verify(platformTextInputService, times(1)).startInput(
                 eq(value),
-                eq(keyboardType),
-                eq(imeAction),
                 eq(keyboardOptions),
                 any(), // onEditCommand
                 any() // onImeActionPerformed
diff --git a/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/SelectionContainerTest.kt b/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/SelectionContainerTest.kt
index ea848c5..3ba2377 100644
--- a/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/SelectionContainerTest.kt
+++ b/compose/foundation/foundation-text/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/SelectionContainerTest.kt
@@ -44,6 +44,7 @@
 import androidx.compose.ui.selection.SelectionContainer
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
 import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.InternalTextApi
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontStyle
 import androidx.compose.ui.text.font.FontWeight
@@ -75,6 +76,8 @@
 import kotlin.math.max
 import kotlin.math.roundToInt
 
+@Suppress("DEPRECATION")
+@OptIn(InternalTextApi::class)
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 class SelectionContainerTest {
diff --git a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
index bc7c859..b1a5ce0 100644
--- a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
+++ b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
@@ -93,7 +93,6 @@
 import androidx.compose.ui.text.input.EditProcessor
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.KeyboardOptions
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.NO_SESSION
 import androidx.compose.ui.text.input.OffsetMap
 import androidx.compose.ui.text.input.TextFieldValue
@@ -129,13 +128,6 @@
  * @param onValueChange Called when the input service updates the values in [TextFieldValue].
  * @param modifier optional [Modifier] for this text field.
  * @param textStyle Style configuration that applies at character level such as color, font etc.
- * @param keyboardType The keyboard type to be used in this text field. Note that this input type
- * is honored by IME and shows corresponding keyboard but this is not guaranteed. For example,
- * some IME may send non-ASCII character even if you set [KeyboardType.Ascii].
- * @param imeAction The IME action. This IME action is honored by IME and may show specific icons
- * on the keyboard. For example, search icon may be shown if [ImeAction.Search] is specified.
- * Then, when user tap that key, the [onImeActionPerformed] callback is called with specified
- * ImeAction.
  * @param onImeActionPerformed Called when the input service requested an IME action. When the
  * input service emitted an IME action, this callback is called with the emitted IME action. Note
  * that this IME action may be different from what you specified in [imeAction].
@@ -163,8 +155,6 @@
     modifier: Modifier = Modifier,
     onValueChange: (TextFieldValue) -> Unit,
     textStyle: TextStyle = TextStyle.Default,
-    keyboardType: KeyboardType = KeyboardType.Text,
-    imeAction: ImeAction = ImeAction.Unspecified,
     onImeActionPerformed: (ImeAction) -> Unit = {},
     visualTransformation: VisualTransformation = VisualTransformation.None,
     onTextLayout: (TextLayoutResult) -> Unit = {},
@@ -247,8 +237,6 @@
                 textInputService,
                 value,
                 state.processor,
-                keyboardType,
-                imeAction,
                 keyboardOptions,
                 onValueChangeWrapper,
                 onImeActionPerformedWrapper
@@ -361,7 +349,7 @@
     }
 
     val semanticsModifier = Modifier.semantics {
-        this.imeAction = imeAction
+        this.imeAction = keyboardOptions.imeAction
         this.supportsInputMethods()
         this.text = AnnotatedString(value.text)
         this.textSelectionRange = value.selection
@@ -428,8 +416,7 @@
         }
     }
 
-    val cursorModifier =
-        Modifier.cursor(state, value, offsetMap, cursorColor)
+    val cursorModifier = Modifier.cursor(state, value, offsetMap, cursorColor)
 
     onDispose { manager.hideSelectionToolbar() }
 
@@ -471,9 +458,10 @@
         if (state.hasFocus && state.selectionIsOn) {
             manager.state?.layoutResult?.let {
                 if (!value.selection.collapsed) {
-                    val startDirection = it.getBidiRunDirection(value.selection.start)
-                    val endDirection =
-                        it.getBidiRunDirection(max(value.selection.end - 1, 0))
+                    val startOffset = offsetMap.originalToTransformed(value.selection.start)
+                    val endOffset = offsetMap.originalToTransformed(value.selection.end)
+                    val startDirection = it.getBidiRunDirection(startOffset)
+                    val endDirection = it.getBidiRunDirection(max(endOffset - 1, 0))
                     val directions = Pair(startDirection, endDirection)
                     TextFieldSelectionHandle(
                         isStartHandle = true,
diff --git a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.kt b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.kt
index 7c22f19..33dca06 100644
--- a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.kt
+++ b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.kt
@@ -41,7 +41,6 @@
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.InputSessionToken
 import androidx.compose.ui.text.input.KeyboardOptions
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.OffsetMap
 import androidx.compose.ui.text.input.SetSelectionEditOp
 import androidx.compose.ui.text.input.TextFieldValue
@@ -316,25 +315,21 @@
          * @param textInputService The text input service
          * @param value The editor state
          * @param editProcessor The edit processor
-         * @param keyboardType The keyboard type
          * @param onValueChange The callback called when the new editor state arrives.
          * @param onImeActionPerformed The callback called when the editor action arrives.
+         * @param keyboardOptions Keyboard configuration such as single line, auto correct etc.
          */
         @JvmStatic
         internal fun onFocus(
             textInputService: TextInputService?,
             value: TextFieldValue,
             editProcessor: EditProcessor,
-            keyboardType: KeyboardType,
-            imeAction: ImeAction,
             keyboardOptions: KeyboardOptions,
             onValueChange: (TextFieldValue) -> Unit,
             onImeActionPerformed: (ImeAction) -> Unit
         ): InputSessionToken {
             val inputSessionToken = textInputService?.startInput(
                 value = TextFieldValue(value.text, value.selection, value.composition),
-                keyboardType = keyboardType,
-                imeAction = imeAction,
                 keyboardOptions = keyboardOptions,
                  onEditCommand(it, editProcessor, onValueChange) },
                 >
diff --git a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt
index acd8264..61e66f9 100644
--- a/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt
+++ b/compose/foundation/foundation-text/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.kt
@@ -34,6 +34,7 @@
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.InternalTextApi
 import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.constrain
 import androidx.compose.ui.text.input.OffsetMap
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.getSelectedText
@@ -123,7 +124,7 @@
                     )
                     hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
 
-                    val newValue = TextFieldValue(
+                    val newValue = createTextFieldValue(
                         text = value.text,
                         selection = TextRange(offset, offset)
                     )
@@ -137,13 +138,11 @@
             if (value.text == "") return
             enterSelectionMode()
             state?.layoutResult?.let { layoutResult ->
-                val offset = offsetMap.transformedToOriginal(
-                    layoutResult.getOffsetForPosition(pxPosition)
-                )
+                val offset = layoutResult.getOffsetForPosition(pxPosition)
                 updateSelection(
                     value = value,
-                    startOffset = offset,
-                    endOffset = offset,
+                    transformedStartOffset = offset,
+                    transformedEndOffset = offset,
                     isStartHandle = true,
                     wordBasedSelection = true
                 )
@@ -159,12 +158,13 @@
             dragTotalDistance += dragDistance
             state?.layoutResult?.let { layoutResult ->
                 val startOffset = layoutResult.getOffsetForPosition(dragBeginPosition)
-                val endOffset =
-                    layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
+                val endOffset = layoutResult.getOffsetForPosition(
+                    dragBeginPosition + dragTotalDistance
+                )
                 updateSelection(
                     value = value,
-                    startOffset = startOffset,
-                    endOffset = endOffset,
+                    transformedStartOffset = startOffset,
+                    transformedEndOffset = endOffset,
                     isStartHandle = true,
                     wordBasedSelection = true
                 )
@@ -199,22 +199,20 @@
                 dragTotalDistance += dragDistance
 
                 state?.layoutResult?.let { layoutResult ->
-                    val startOffset =
-                        if (isStartHandle)
-                            layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
-                        else
-                            value.selection.start
+                    val startOffset = if (isStartHandle)
+                        layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
+                    else
+                        offsetMap.originalToTransformed(value.selection.start)
 
-                    val endOffset =
-                        if (isStartHandle)
-                            value.selection.end
-                        else
-                            layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
+                    val endOffset = if (isStartHandle)
+                        offsetMap.originalToTransformed(value.selection.end)
+                    else
+                        layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
 
                     updateSelection(
                         value = value,
-                        startOffset = startOffset,
-                        endOffset = endOffset,
+                        transformedStartOffset = startOffset,
+                        transformedEndOffset = endOffset,
                         isStartHandle = isStartHandle,
                         wordBasedSelection = false
                     )
@@ -275,10 +273,11 @@
     internal fun copy() {
         if (value.selection.collapsed) return
 
+        // TODO(b/171947959) check if original or transformed should be copied
         clipboardManager?.setText(AnnotatedString(value.getSelectedText()))
 
         val newCursorOffset = value.selection.max
-        val newValue = TextFieldValue(
+        val newValue = createTextFieldValue(
             text = value.text,
             selection = TextRange(newCursorOffset, newCursorOffset)
         )
@@ -303,7 +302,7 @@
             value.getTextAfterSelection(value.text.length)
         val newCursorOffset = value.selection.min + text.length
 
-        val newValue = TextFieldValue(
+        val newValue = createTextFieldValue(
             text = newText,
             selection = TextRange(newCursorOffset, newCursorOffset)
         )
@@ -323,13 +322,14 @@
     internal fun cut() {
         if (value.selection.collapsed) return
 
+        // TODO(b/171947959) check if original or transformed should be cut
         clipboardManager?.setText(AnnotatedString(value.getSelectedText()))
 
         val newText = value.getTextBeforeSelection(value.text.length) +
             value.getTextAfterSelection(value.text.length)
         val newCursorOffset = value.selection.min
 
-        val newValue = TextFieldValue(
+        val newValue = createTextFieldValue(
             text = newText,
             selection = TextRange(newCursorOffset, newCursorOffset)
         )
@@ -341,7 +341,7 @@
     internal fun selectAll() {
         setSelectionStatus(true)
 
-        val newValue = TextFieldValue(
+        val newValue = createTextFieldValue(
             text = value.text,
             selection = TextRange(0, value.text.length)
         )
@@ -352,14 +352,14 @@
         return if (isStartHandle)
             getSelectionHandleCoordinates(
                 textLayoutResult = state?.layoutResult!!,
-                offset = value.selection.start,
+                offset = offsetMap.originalToTransformed(value.selection.start),
                 isStart = true,
                 areHandlesCrossed = value.selection.reversed
             )
         else
             getSelectionHandleCoordinates(
                 textLayoutResult = state?.layoutResult!!,
-                offset = value.selection.end,
+                offset = offsetMap.originalToTransformed(value.selection.end),
                 isStart = false,
                 areHandlesCrossed = value.selection.reversed
             )
@@ -471,28 +471,38 @@
 
     private fun updateSelection(
         value: TextFieldValue,
-        startOffset: Int,
-        endOffset: Int,
+        transformedStartOffset: Int,
+        transformedEndOffset: Int,
         isStartHandle: Boolean,
         wordBasedSelection: Boolean
     ) {
-        val range = getTextFieldSelection(
+        val transformedSelection = TextRange(
+            offsetMap.originalToTransformed(value.selection.start),
+            offsetMap.originalToTransformed(value.selection.end)
+        )
+
+        val newTransformedSelection = getTextFieldSelection(
             textLayoutResult = state?.layoutResult,
-            rawStartOffset = startOffset,
-            rawEndOffset = endOffset,
-            previousSelection = if (value.selection.collapsed) null else value.selection,
-            previousHandlesCrossed = value.selection.reversed,
+            rawStartOffset = transformedStartOffset,
+            rawEndOffset = transformedEndOffset,
+            previousSelection = if (transformedSelection.collapsed) null else transformedSelection,
+            previousHandlesCrossed = transformedSelection.reversed,
             isStartHandle = isStartHandle,
             wordBasedSelection = wordBasedSelection
         )
 
-        if (range == value.selection) return
+        val originalSelection = TextRange(
+            start = offsetMap.transformedToOriginal(newTransformedSelection.start),
+            end = offsetMap.transformedToOriginal(newTransformedSelection.end)
+        )
+
+        if (originalSelection == value.selection) return
 
         hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
 
-        val newValue = TextFieldValue(
+        val newValue = createTextFieldValue(
             text = value.text,
-            selection = range
+            selection = originalSelection
         )
         onValueChange(newValue)
     }
@@ -503,6 +513,13 @@
         }
     }
 
+    private fun createTextFieldValue(
+        text: String,
+        selection: TextRange,
+    ): TextFieldValue {
+        return TextFieldValue(text = text, selection = selection.constrain(0, text.length))
+    }
+
     /** Returns true if the screen coordinates position (x,y) corresponds to a character displayed
      * in the view. Returns false when the position is in the empty space of left/right of text.
      */
diff --git a/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/TextFieldDelegateTest.kt b/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/TextFieldDelegateTest.kt
index 1ab27c5..5f54d28 100644
--- a/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/TextFieldDelegateTest.kt
+++ b/compose/foundation/foundation-text/src/test/kotlin/androidx/compose/foundation/text/TextFieldDelegateTest.kt
@@ -159,17 +159,15 @@
         val editorState = TextFieldValue(text = "Hello, World", selection = TextRange(1))
         val keyboardOptions = KeyboardOptions(
             singleLine = true,
-            capitalization = KeyboardCapitalization.Sentences
+            capitalization = KeyboardCapitalization.Sentences,
+            keyboardType = KeyboardType.Phone,
+            imeAction = ImeAction.Search
         )
-        val keyboardType = KeyboardType.Phone
-        val imeAction = ImeAction.Search
 
         TextFieldDelegate.onFocus(
             textInputService = textInputService,
             value = editorState,
             editProcessor = processor,
-            keyboardType = keyboardType,
-            imeAction = imeAction,
             keyboardOptions = keyboardOptions,
             >
             >
@@ -181,8 +179,6 @@
                     selection = editorState.selection
                 )
             ),
-            eq(keyboardType),
-            eq(imeAction),
             eq(keyboardOptions),
             any(),
             eq(onEditorActionPerformed)
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/SoftwareKeyboardTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/SoftwareKeyboardTest.kt
index e0c786e..08b0281 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/SoftwareKeyboardTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/SoftwareKeyboardTest.kt
@@ -52,7 +52,7 @@
         val textInputService = mock<TextInputService>()
         val inputSessionToken = 10 // any positive number is fine.
 
-        whenever(textInputService.startInput(any(), any(), any(), any(), any(), any()))
+        whenever(textInputService.startInput(any(), any(), any(), any()))
             .thenReturn(inputSessionToken)
 
         val onTextInputStarted: (SoftwareKeyboardController) -> Unit = mock()
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldOnValueChangeTextFieldValueTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldOnValueChangeTextFieldValueTest.kt
index 84d7f48..a4ecfbc 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldOnValueChangeTextFieldValueTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldOnValueChangeTextFieldValueTest.kt
@@ -67,7 +67,7 @@
         val textInputService = mock<TextInputService>()
         val inputSessionToken = 10 // any positive number is fine.
 
-        whenever(textInputService.startInput(any(), any(), any(), any(), any(), any()))
+        whenever(textInputService.startInput(any(), any(), any(), any()))
             .thenReturn(inputSessionToken)
 
         rule.setContent {
@@ -101,8 +101,6 @@
             val  -> Unit>()
             verify(textInputService, times(1)).startInput(
                 value = any(),
-                keyboardType = any(),
-                imeAction = any(),
                 keyboardOptions = any(),
                 >
                 >
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldTest.kt
index 89e2d9b..20822be 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TextFieldTest.kt
@@ -148,7 +148,7 @@
         val textInputService = mock<TextInputService>()
         val inputSessionToken = 10 // any positive number is fine.
 
-        whenever(textInputService.startInput(any(), any(), any(), any(), any(), any()))
+        whenever(textInputService.startInput(any(), any(), any(), any()))
             .thenReturn(inputSessionToken)
 
         rule.setContent {
@@ -167,8 +167,6 @@
             val  -> Unit>()
             verify(textInputService, times(1)).startInput(
                 value = any(),
-                keyboardType = any(),
-                imeAction = any(),
                 keyboardOptions = any(),
                 >
                 >
@@ -221,7 +219,7 @@
         val textInputService = mock<TextInputService>()
         val inputSessionToken = 10 // any positive number is fine.
 
-        whenever(textInputService.startInput(any(), any(), any(), any(), any(), any()))
+        whenever(textInputService.startInput(any(), any(), any(), any()))
             .thenReturn(inputSessionToken)
 
         rule.setContent {
@@ -240,8 +238,6 @@
             val  -> Unit>()
             verify(textInputService, times(1)).startInput(
                 value = any(),
-                keyboardType = any(),
-                imeAction = any(),
                 keyboardOptions = any(),
                 >
                 >
@@ -281,7 +277,7 @@
         val textInputService = mock<TextInputService>()
         val inputSessionToken = 10 // any positive number is fine.
 
-        whenever(textInputService.startInput(any(), any(), any(), any(), any(), any()))
+        whenever(textInputService.startInput(any(), any(), any(), any()))
             .thenReturn(inputSessionToken)
 
         val onTextLayout: (TextLayoutResult) -> Unit = mock()
@@ -309,8 +305,6 @@
             val  -> Unit>()
             verify(textInputService, times(1)).startInput(
                 value = any(),
-                keyboardType = any(),
-                imeAction = any(),
                 keyboardOptions = any(),
                 >
                 >
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt
index cbf9393..38feffc 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicTextField.kt
@@ -23,6 +23,7 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.InternalTextApi
 import androidx.compose.ui.text.SoftwareKeyboardController
 import androidx.compose.ui.text.TextLayoutResult
@@ -30,6 +31,7 @@
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.constrain
 import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardOptions
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.VisualTransformation
@@ -189,7 +191,7 @@
  * @param cursorColor Color of the cursor. If [Color.Unspecified], there will be no cursor drawn
  */
 @Composable
-@OptIn(InternalTextApi::class)
+@OptIn(InternalTextApi::class, ExperimentalTextApi::class)
 fun BasicTextField(
     value: TextFieldValue,
     onValueChange: (TextFieldValue) -> Unit,
@@ -204,16 +206,18 @@
     cursorColor: Color = Color.Black
 ) {
     CoreTextField(
-        value,
-        modifier,
-        onValueChange,
-        textStyle,
-        keyboardType,
-        imeAction,
-        onImeActionPerformed,
-        visualTransformation,
-        onTextLayout,
-        onTextInputStarted,
-        cursorColor
+        value = value,
+        modifier = modifier,
+        >
+        textStyle = textStyle,
+        >
+        visualTransformation = visualTransformation,
+        >
+        >
+        cursorColor = cursorColor,
+        keyboardOptions = KeyboardOptions(
+            keyboardType = keyboardType,
+            imeAction = imeAction
+        ),
     )
 }
\ No newline at end of file
diff --git a/compose/integration-tests/src/main/java/androidx/ui/integration/test/core/text/TextFieldToggleTextTestCase.kt b/compose/integration-tests/src/main/java/androidx/ui/integration/test/core/text/TextFieldToggleTextTestCase.kt
index d2e4968..8229da8 100644
--- a/compose/integration-tests/src/main/java/androidx/ui/integration/test/core/text/TextFieldToggleTextTestCase.kt
+++ b/compose/integration-tests/src/main/java/androidx/ui/integration/test/core/text/TextFieldToggleTextTestCase.kt
@@ -37,7 +37,6 @@
 import androidx.compose.ui.text.input.EditOperation
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.KeyboardOptions
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.PlatformTextInputService
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.TextInputService
@@ -105,8 +104,6 @@
     private class TestPlatformTextInputService : PlatformTextInputService {
         override fun startInput(
             value: TextFieldValue,
-            keyboardType: KeyboardType,
-            imeAction: ImeAction,
             keyboardOptions: KeyboardOptions,
             onEditCommand: (List<EditOperation>) -> Unit,
             onImeActionPerformed: (ImeAction) -> Unit
diff --git a/compose/material/material/build.gradle b/compose/material/material/build.gradle
index f9b13d4..84baf44 100644
--- a/compose/material/material/build.gradle
+++ b/compose/material/material/build.gradle
@@ -149,9 +149,6 @@
 
 // Screenshot tests related setup
 android {
-    defaultConfig {
-        testInstrumentationRunnerArgument("thisisignored", "thisisignored --no-isolated-storage")
-    }
     sourceSets.androidTest.assets.srcDirs +=
             project.rootDir.absolutePath + "/../../golden/compose/material/material"
 }
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
index bb7e4d1..262d15c 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
@@ -52,8 +52,10 @@
 import androidx.compose.ui.test.performClick
 import androidx.compose.ui.test.performGesture
 import androidx.compose.ui.test.performImeAction
+import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.SoftwareKeyboardController
 import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardOptions
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.PasswordVisualTransformation
 import androidx.compose.ui.text.input.TextFieldValue
@@ -585,6 +587,7 @@
         }
     }
 
+    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testOutlinedTextField_imeActionAndKeyboardTypePropagatedDownstream() {
         val textInputService = mock<TextInputService>()
@@ -609,9 +612,12 @@
         rule.runOnIdle {
             verify(textInputService, atLeastOnce()).startInput(
                 value = any(),
-                keyboardType = eq(KeyboardType.Email),
-                imeAction = eq(ImeAction.Go),
-                keyboardOptions = any(),
+                keyboardOptions = eq(
+                    KeyboardOptions(
+                        keyboardType = KeyboardType.Email,
+                        imeAction = ImeAction.Go
+                    )
+                ),
                 >
                 >
             )
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
index c45a667..44146de 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
@@ -63,8 +63,10 @@
 import androidx.compose.ui.test.performClick
 import androidx.compose.ui.test.performGesture
 import androidx.compose.ui.test.performImeAction
+import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.SoftwareKeyboardController
 import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardOptions
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.PasswordVisualTransformation
 import androidx.compose.ui.text.input.TextFieldValue
@@ -738,6 +740,7 @@
         }
     }
 
+    @OptIn(ExperimentalTextApi::class)
     @Test
     fun testTextField_imeActionAndKeyboardTypePropagatedDownstream() {
         val textInputService = mock<TextInputService>()
@@ -762,9 +765,12 @@
         rule.runOnIdle {
             verify(textInputService, atLeastOnce()).startInput(
                 value = any(),
-                keyboardType = eq(KeyboardType.Email),
-                imeAction = eq(ImeAction.Go),
-                keyboardOptions = any(),
+                keyboardOptions = eq(
+                    KeyboardOptions(
+                        keyboardType = KeyboardType.Email,
+                        imeAction = ImeAction.Go
+                    )
+                ),
                 >
                 >
             )
diff --git a/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/junit4/TextInputServiceForTests.kt b/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/junit4/TextInputServiceForTests.kt
index bf683e3..4d33f9f 100644
--- a/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/junit4/TextInputServiceForTests.kt
+++ b/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/junit4/TextInputServiceForTests.kt
@@ -21,7 +21,6 @@
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.InputSessionToken
 import androidx.compose.ui.text.input.KeyboardOptions
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.PlatformTextInputService
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.TextInputService
@@ -43,8 +42,6 @@
 
     override fun startInput(
         value: TextFieldValue,
-        keyboardType: KeyboardType,
-        imeAction: ImeAction,
         keyboardOptions: KeyboardOptions,
         onEditCommand: (List<EditOperation>) -> Unit,
         onImeActionPerformed: (ImeAction) -> Unit
@@ -53,8 +50,6 @@
         this.>
         return super.startInput(
             value,
-            keyboardType,
-            imeAction,
             keyboardOptions,
             onEditCommand,
             onImeActionPerformed
diff --git a/compose/ui/ui-text/api/current.txt b/compose/ui/ui-text/api/current.txt
index 6b140dc..4c8e03a 100644
--- a/compose/ui/ui-text/api/current.txt
+++ b/compose/ui/ui-text/api/current.txt
@@ -791,17 +791,23 @@
   }
 
   @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public final class KeyboardOptions {
-    ctor public KeyboardOptions(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect);
+    ctor public KeyboardOptions(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction);
     ctor public KeyboardOptions();
     method public boolean component1();
     method public androidx.compose.ui.text.input.KeyboardCapitalization component2();
     method public boolean component3();
-    method @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.input.KeyboardOptions copy(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect);
+    method public androidx.compose.ui.text.input.KeyboardType component4();
+    method public androidx.compose.ui.text.input.ImeAction component5();
+    method @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.input.KeyboardOptions copy(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction);
     method public boolean getAutoCorrect();
     method public androidx.compose.ui.text.input.KeyboardCapitalization getCapitalization();
+    method public androidx.compose.ui.text.input.ImeAction getImeAction();
+    method public androidx.compose.ui.text.input.KeyboardType getKeyboardType();
     method public boolean getSingleLine();
     property public final boolean autoCorrect;
     property public final androidx.compose.ui.text.input.KeyboardCapitalization capitalization;
+    property public final androidx.compose.ui.text.input.ImeAction imeAction;
+    property public final androidx.compose.ui.text.input.KeyboardType keyboardType;
     property public final boolean singleLine;
     field public static final androidx.compose.ui.text.input.KeyboardOptions.Companion Companion;
   }
@@ -857,7 +863,7 @@
     method public void notifyFocusedRect(androidx.compose.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.compose.ui.text.input.TextFieldValue value);
     method public void showSoftwareKeyboard();
-    method public void startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
+    method public void startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
     method public void stopInput();
   }
 
@@ -928,7 +934,7 @@
     method public void notifyFocusedRect(int token, androidx.compose.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.compose.ui.text.input.TextFieldValue value);
     method public void showSoftwareKeyboard(int token);
-    method public int startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
+    method public int startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
     method public void stopInput(int token);
   }
 
diff --git a/compose/ui/ui-text/api/public_plus_experimental_current.txt b/compose/ui/ui-text/api/public_plus_experimental_current.txt
index 6b140dc..4c8e03a 100644
--- a/compose/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-text/api/public_plus_experimental_current.txt
@@ -791,17 +791,23 @@
   }
 
   @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public final class KeyboardOptions {
-    ctor public KeyboardOptions(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect);
+    ctor public KeyboardOptions(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction);
     ctor public KeyboardOptions();
     method public boolean component1();
     method public androidx.compose.ui.text.input.KeyboardCapitalization component2();
     method public boolean component3();
-    method @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.input.KeyboardOptions copy(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect);
+    method public androidx.compose.ui.text.input.KeyboardType component4();
+    method public androidx.compose.ui.text.input.ImeAction component5();
+    method @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.input.KeyboardOptions copy(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction);
     method public boolean getAutoCorrect();
     method public androidx.compose.ui.text.input.KeyboardCapitalization getCapitalization();
+    method public androidx.compose.ui.text.input.ImeAction getImeAction();
+    method public androidx.compose.ui.text.input.KeyboardType getKeyboardType();
     method public boolean getSingleLine();
     property public final boolean autoCorrect;
     property public final androidx.compose.ui.text.input.KeyboardCapitalization capitalization;
+    property public final androidx.compose.ui.text.input.ImeAction imeAction;
+    property public final androidx.compose.ui.text.input.KeyboardType keyboardType;
     property public final boolean singleLine;
     field public static final androidx.compose.ui.text.input.KeyboardOptions.Companion Companion;
   }
@@ -857,7 +863,7 @@
     method public void notifyFocusedRect(androidx.compose.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.compose.ui.text.input.TextFieldValue value);
     method public void showSoftwareKeyboard();
-    method public void startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
+    method public void startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
     method public void stopInput();
   }
 
@@ -928,7 +934,7 @@
     method public void notifyFocusedRect(int token, androidx.compose.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.compose.ui.text.input.TextFieldValue value);
     method public void showSoftwareKeyboard(int token);
-    method public int startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
+    method public int startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
     method public void stopInput(int token);
   }
 
diff --git a/compose/ui/ui-text/api/restricted_current.txt b/compose/ui/ui-text/api/restricted_current.txt
index 6b140dc..4c8e03a 100644
--- a/compose/ui/ui-text/api/restricted_current.txt
+++ b/compose/ui/ui-text/api/restricted_current.txt
@@ -791,17 +791,23 @@
   }
 
   @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public final class KeyboardOptions {
-    ctor public KeyboardOptions(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect);
+    ctor public KeyboardOptions(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction);
     ctor public KeyboardOptions();
     method public boolean component1();
     method public androidx.compose.ui.text.input.KeyboardCapitalization component2();
     method public boolean component3();
-    method @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.input.KeyboardOptions copy(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect);
+    method public androidx.compose.ui.text.input.KeyboardType component4();
+    method public androidx.compose.ui.text.input.ImeAction component5();
+    method @androidx.compose.runtime.Immutable @androidx.compose.ui.text.ExperimentalTextApi public androidx.compose.ui.text.input.KeyboardOptions copy(boolean singleLine, androidx.compose.ui.text.input.KeyboardCapitalization capitalization, boolean autoCorrect, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction);
     method public boolean getAutoCorrect();
     method public androidx.compose.ui.text.input.KeyboardCapitalization getCapitalization();
+    method public androidx.compose.ui.text.input.ImeAction getImeAction();
+    method public androidx.compose.ui.text.input.KeyboardType getKeyboardType();
     method public boolean getSingleLine();
     property public final boolean autoCorrect;
     property public final androidx.compose.ui.text.input.KeyboardCapitalization capitalization;
+    property public final androidx.compose.ui.text.input.ImeAction imeAction;
+    property public final androidx.compose.ui.text.input.KeyboardType keyboardType;
     property public final boolean singleLine;
     field public static final androidx.compose.ui.text.input.KeyboardOptions.Companion Companion;
   }
@@ -857,7 +863,7 @@
     method public void notifyFocusedRect(androidx.compose.ui.geometry.Rect rect);
     method public void onStateUpdated(androidx.compose.ui.text.input.TextFieldValue value);
     method public void showSoftwareKeyboard();
-    method public void startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
+    method public void startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
     method public void stopInput();
   }
 
@@ -928,7 +934,7 @@
     method public void notifyFocusedRect(int token, androidx.compose.ui.geometry.Rect rect);
     method public void onStateUpdated(int token, androidx.compose.ui.text.input.TextFieldValue value);
     method public void showSoftwareKeyboard(int token);
-    method public int startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardType keyboardType, androidx.compose.ui.text.input.ImeAction imeAction, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
+    method public int startInput(androidx.compose.ui.text.input.TextFieldValue value, androidx.compose.ui.text.input.KeyboardOptions keyboardOptions, kotlin.jvm.functions.Function1<? super java.util.List<? extends androidx.compose.ui.text.input.EditOperation>,kotlin.Unit> onEditCommand, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.ImeAction,kotlin.Unit> onImeActionPerformed);
     method public void stopInput(int token);
   }
 
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/KeyboardOptions.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/KeyboardOptions.kt
index 4ff2536..0a44c86 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/KeyboardOptions.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/KeyboardOptions.kt
@@ -33,13 +33,21 @@
  * text based [KeyboardType]s such as [KeyboardType.Email], [KeyboardType.Uri]. It will not be
  * applied to [KeyboardType]s such as [KeyboardType.Number]. Most of software keyboard
  * implementations ignore this value for [KeyboardType]s such as [KeyboardType.Text].
+ * @param keyboardType The keyboard type to be used in this text field. Note that this input type
+ * is honored by IME and shows corresponding keyboard but this is not guaranteed. For example,
+ * some IME may send non-ASCII character even if you set [KeyboardType.Ascii].
+ * @param imeAction The IME action. This IME action is honored by IME and may show specific icons
+ * on the keyboard. For example, search icon may be shown if [ImeAction.Search] is specified.
+ * When [singleLine] is false, the IME might show return key rather than the action requested here.
  */
 @ExperimentalTextApi
 @Immutable
 data class KeyboardOptions(
     val singleLine: Boolean = false,
     val capitalization: KeyboardCapitalization = KeyboardCapitalization.None,
-    val autoCorrect: Boolean = true
+    val autoCorrect: Boolean = true,
+    val keyboardType: KeyboardType = KeyboardType.Text,
+    val imeAction: ImeAction = ImeAction.Unspecified,
 ) {
     companion object {
         val Default = KeyboardOptions()
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/TextInputService.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/TextInputService.kt
index af755c7..828c2e2 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/TextInputService.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/TextInputService.kt
@@ -61,16 +61,12 @@
      */
     open fun startInput(
         value: TextFieldValue,
-        keyboardType: KeyboardType,
-        imeAction: ImeAction,
         keyboardOptions: KeyboardOptions,
         onEditCommand: (List<EditOperation>) -> Unit,
         onImeActionPerformed: (ImeAction) -> Unit
     ): InputSessionToken {
         platformTextInputService.startInput(
             value,
-            keyboardType,
-            imeAction,
             keyboardOptions,
             onEditCommand,
             onImeActionPerformed
@@ -131,8 +127,6 @@
      */
     fun startInput(
         value: TextFieldValue,
-        keyboardType: KeyboardType,
-        imeAction: ImeAction,
         keyboardOptions: KeyboardOptions,
         onEditCommand: (List<EditOperation>) -> Unit,
         onImeActionPerformed: (ImeAction) -> Unit
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextInputServiceTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextInputServiceTest.kt
index 48ae334..b52651f 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextInputServiceTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextInputServiceTest.kt
@@ -19,9 +19,7 @@
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.KeyboardOptions
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.PlatformTextInputService
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.TextInputService
@@ -48,16 +46,12 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
         )
         val secondToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -74,8 +68,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -93,8 +85,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -103,8 +93,6 @@
         // Start another session. The firstToken is now expired.
         textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -122,8 +110,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -141,8 +127,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -151,8 +135,6 @@
         // Start another session. The firstToken is now expired.
         textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -170,8 +152,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -190,8 +170,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -200,8 +178,6 @@
         // Start another session. The firstToken is now expired.
         textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -220,8 +196,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -240,8 +214,6 @@
 
         val firstToken = textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
@@ -250,8 +222,6 @@
         // Start another session. The firstToken is now expired.
         textInputService.startInput(
             TextFieldValue(),
-            KeyboardType.Text,
-            ImeAction.NoAction,
             KeyboardOptions.Default,
             {}, // onEditCommand
             {} // onImeActionPerformed
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 408faf1..5d864f1 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -2304,7 +2304,8 @@
 
   public final class SelectionContainerKt {
     method @androidx.compose.runtime.Composable public static void DisableSelection(kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.ui.selection.Selection? selection, kotlin.jvm.functions.Function1<? super androidx.compose.ui.selection.Selection,kotlin.Unit> onSelectionChange, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.runtime.Composable public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.ui.selection.Selection? selection, kotlin.jvm.functions.Function1<? super androidx.compose.ui.selection.Selection,kotlin.Unit> onSelectionChange, kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class SelectionHandlesKt {
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index 408faf1..5d864f1 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -2304,7 +2304,8 @@
 
   public final class SelectionContainerKt {
     method @androidx.compose.runtime.Composable public static void DisableSelection(kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.ui.selection.Selection? selection, kotlin.jvm.functions.Function1<? super androidx.compose.ui.selection.Selection,kotlin.Unit> onSelectionChange, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.runtime.Composable public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.ui.selection.Selection? selection, kotlin.jvm.functions.Function1<? super androidx.compose.ui.selection.Selection,kotlin.Unit> onSelectionChange, kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class SelectionHandlesKt {
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 80235fd..0bbc3bd 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -2381,7 +2381,8 @@
 
   public final class SelectionContainerKt {
     method @androidx.compose.runtime.Composable public static void DisableSelection(kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    method @androidx.compose.runtime.Composable public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.ui.selection.Selection? selection, kotlin.jvm.functions.Function1<? super androidx.compose.ui.selection.Selection,kotlin.Unit> onSelectionChange, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @androidx.compose.runtime.Composable public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+    method @Deprecated @androidx.compose.runtime.Composable @androidx.compose.ui.text.InternalTextApi public static void SelectionContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.ui.selection.Selection? selection, kotlin.jvm.functions.Function1<? super androidx.compose.ui.selection.Selection,kotlin.Unit> onSelectionChange, kotlin.jvm.functions.Function0<kotlin.Unit> children);
   }
 
   public final class SelectionHandlesKt {
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SelectionSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SelectionSample.kt
new file mode 100644
index 0000000..2735be2
--- /dev/null
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SelectionSample.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.compose.ui.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.Text
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.selection.DisableSelection
+import androidx.compose.ui.selection.SelectionContainer
+
+@Sampled
+@Composable
+fun SelectionSample() {
+    SelectionContainer {
+        Column {
+            Text("Text 1")
+            Text("Text 2")
+            Text("טקסט 3")
+        }
+    }
+}
+
+@Sampled
+@Composable
+fun DisableSelectionSample() {
+    SelectionContainer {
+        Column {
+            Text("Text 1")
+
+            DisableSelection {
+                Text("Text 2")
+                Text("טקסט 3")
+            }
+
+            Text("Text 3")
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawLayerTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawLayerTest.kt
index 42cd2f7..34a1af6 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawLayerTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/DrawLayerTest.kt
@@ -50,13 +50,12 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
-import androidx.test.filters.SmallTest
 import org.junit.Assert.assertEquals
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 
-@SmallTest
+@MediumTest
 @RunWith(AndroidJUnit4::class)
 class DrawLayerTest {
     @Suppress("DEPRECATION")
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.kt
index 5097dbf..347de95 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.kt
@@ -44,8 +44,6 @@
     private var onImeActionPerformed: (ImeAction) -> Unit = {}
 
     private var state = TextFieldValue(text = "", selection = TextRange.Zero)
-    private var keyboardType = KeyboardType.Text
-    private var imeAction = ImeAction.Unspecified
     private var keyboardOptions = KeyboardOptions.Default
     private var ic: RecordingInputConnection? = null
     private var focusedRect: android.graphics.Rect? = null
@@ -80,7 +78,7 @@
         if (!editorHasFocus) {
             return null
         }
-        fillEditorInfo(keyboardType, imeAction, keyboardOptions, outAttrs)
+        fillEditorInfo(keyboardOptions, outAttrs)
 
         return RecordingInputConnection(
             initState = state,
@@ -104,8 +102,6 @@
 
     override fun startInput(
         value: TextFieldValue,
-        keyboardType: KeyboardType,
-        imeAction: ImeAction,
         keyboardOptions: KeyboardOptions,
         onEditCommand: (List<EditOperation>) -> Unit,
         onImeActionPerformed: (ImeAction) -> Unit
@@ -113,8 +109,6 @@
         imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
         editorHasFocus = true
         state = value
-        this.keyboardType = keyboardType
-        this.imeAction = imeAction
         this.keyboardOptions = keyboardOptions
         this.>
         this.>
@@ -171,12 +165,10 @@
      * Fills necessary info of EditorInfo.
      */
     private fun fillEditorInfo(
-        keyboardType: KeyboardType,
-        imeAction: ImeAction,
         keyboardOptions: KeyboardOptions,
         outInfo: EditorInfo
     ) {
-        outInfo.imeOptions = when (imeAction) {
+        outInfo.imeOptions = when (keyboardOptions.imeAction) {
             ImeAction.Unspecified -> {
                 if (keyboardOptions.singleLine) {
                     // this is the last resort to enable single line
@@ -194,9 +186,11 @@
             ImeAction.Search -> EditorInfo.IME_ACTION_SEARCH
             ImeAction.Send -> EditorInfo.IME_ACTION_SEND
             ImeAction.Done -> EditorInfo.IME_ACTION_DONE
-            else -> throw IllegalArgumentException("Unknown ImeAction: $imeAction")
+            else -> throw IllegalArgumentException(
+                "Unknown ImeAction: ${keyboardOptions.imeAction}"
+            )
         }
-        when (keyboardType) {
+        when (keyboardOptions.keyboardType) {
             KeyboardType.Text -> outInfo.inputType = InputType.TYPE_CLASS_TEXT
             KeyboardType.Ascii -> {
                 outInfo.inputType = InputType.TYPE_CLASS_TEXT
@@ -217,7 +211,9 @@
                 outInfo.inputType =
                     InputType.TYPE_CLASS_NUMBER or EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD
             }
-            else -> throw IllegalArgumentException("Unknown KeyboardType: $keyboardType")
+            else -> throw IllegalArgumentException(
+                "Unknown KeyboardType: ${keyboardOptions.keyboardType}"
+            )
         }
 
         if (!keyboardOptions.singleLine) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionContainer.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionContainer.kt
index 6ae78f3..6293e8a 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionContainer.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/selection/SelectionContainer.kt
@@ -18,7 +18,10 @@
 
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Providers
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.gesture.dragGestureFilter
@@ -30,12 +33,48 @@
 import androidx.compose.ui.text.InternalTextApi
 
 /**
+ * Enables text selection for it's direct or indirection children.
+ *
+ * @sample androidx.compose.ui.samples.SelectionSample
+ */
+@Suppress("DEPRECATION")
+@OptIn(InternalTextApi::class)
+@Composable
+fun SelectionContainer(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
+    var selection by remember { mutableStateOf<Selection?>(null) }
+    SelectionContainer(
+        modifier = modifier,
+        selection = selection,
+        >
+            selection = it
+        },
+        children = children
+    )
+}
+
+/**
+ * Disables text selection for it's direct or indirection children. To use this, simply add this
+ * to wrap one or more text composables.
+ *
+ * @sample androidx.compose.ui.samples.DisableSelectionSample
+ */
+@Composable
+fun DisableSelection(content: @Composable () -> Unit) {
+    Providers(
+        SelectionRegistrarAmbient provides null,
+        children = content
+    )
+}
+
+/**
  * Selection Composable.
  *
  * The selection composable wraps composables and let them to be selectable. It paints the selection
  * area with start and end handles.
  */
 @OptIn(InternalTextApi::class)
+@Deprecated("Please use SelectionContainer with no callback")
+@InternalTextApi
 @Composable
 fun SelectionContainer(
     /** A [Modifier] for SelectionContainer. */
@@ -100,19 +139,6 @@
     }
 }
 
-/**
- * This is for disabling selection for text when the text is inside a SelectionContainer.
- *
- * To use this, simply add this to wrap one or more text composables.
- */
-@Composable
-fun DisableSelection(content: @Composable () -> Unit) {
-    Providers(
-        SelectionRegistrarAmbient provides null,
-        children = content
-    )
-}
-
 @Composable
 private fun SelectionFloatingToolBar(manager: SelectionManager) {
     manager.showSelectionToolbar()
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt
index f8102ed..3f58f6a 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopPlatformInput.kt
@@ -23,7 +23,6 @@
 import androidx.compose.ui.text.input.EditOperation
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.KeyboardOptions
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.MoveCursorEditOp
 import androidx.compose.ui.text.input.PlatformTextInputService
 import androidx.compose.ui.text.input.SetComposingTextEditOp
@@ -67,14 +66,12 @@
 
     override fun startInput(
         value: TextFieldValue,
-        keyboardType: KeyboardType,
-        imeAction: ImeAction,
         keyboardOptions: KeyboardOptions,
         onEditCommand: (List<EditOperation>) -> Unit,
         onImeActionPerformed: (ImeAction) -> Unit
     ) {
         val input = CurrentInput(
-            value, onEditCommand, onImeActionPerformed, imeAction
+            value, onEditCommand, onImeActionPerformed, keyboardOptions.imeAction
         )
         currentInput = input
 
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt
index 69e59d7..42da49c 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt
@@ -58,10 +58,11 @@
     @Test
     fun test_fill_editor_info_text() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Text,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -79,10 +80,11 @@
     @Test
     fun test_fill_editor_info_ascii() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -101,10 +103,11 @@
     @Test
     fun test_fill_editor_info_number() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Number,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -122,10 +125,11 @@
     @Test
     fun test_fill_editor_info_phone() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Phone,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Phone,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -143,10 +147,11 @@
     @Test
     fun test_fill_editor_info_uri() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Uri,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Uri,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -165,10 +170,11 @@
     @Test
     fun test_fill_editor_info_email() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Email,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Email,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -187,10 +193,11 @@
     @Test
     fun test_fill_editor_info_password() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Password,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Password,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -209,10 +216,11 @@
     @Test
     fun test_fill_editor_info_number_password() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.NumberPassword,
-            ImeAction.Unspecified,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.NumberPassword,
+                imeAction = ImeAction.Unspecified
+            ),
             >
             >
         )
@@ -231,10 +239,11 @@
     @Test
     fun test_fill_editor_info_action_none() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.NoAction,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.NoAction
+            ),
             >
             >
         )
@@ -253,10 +262,11 @@
     @Test
     fun test_fill_editor_info_action_go() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Go,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Go
+            ),
             >
             >
         )
@@ -275,10 +285,11 @@
     @Test
     fun test_fill_editor_info_action_next() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Next,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Next
+            ),
             >
             >
         )
@@ -297,10 +308,11 @@
     @Test
     fun test_fill_editor_info_action_previous() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Previous,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Previous
+            ),
             >
             >
         )
@@ -319,10 +331,11 @@
     @Test
     fun test_fill_editor_info_action_search() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Search,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Search,
+            ),
             >
             >
         )
@@ -341,10 +354,11 @@
     @Test
     fun test_fill_editor_info_action_send() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Send,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Send
+            ),
             >
             >
         )
@@ -363,10 +377,11 @@
     @Test
     fun test_fill_editor_info_action_done() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions.Default,
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -385,10 +400,12 @@
     @Test
     fun test_fill_editor_info_multi_line() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(singleLine = false),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -403,10 +420,12 @@
     @Test
     fun test_fill_editor_info_single_line() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(singleLine = true),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                singleLine = true,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -421,10 +440,12 @@
     @Test
     fun test_fill_editor_info_single_line_changes_ime_from_unspecified_to_done() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Text,
-            ImeAction.Unspecified,
-            KeyboardOptions(singleLine = true),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                singleLine = true,
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Unspecified,
+            ),
             >
             >
         )
@@ -439,10 +460,12 @@
     @Test
     fun test_fill_editor_info_multi_line_not_set_when_input_type_is_not_text() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Number,
-            ImeAction.Done,
-            KeyboardOptions(singleLine = false),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -457,10 +480,12 @@
     @Test
     fun test_fill_editor_info_capitalization_none() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(capitalization = KeyboardCapitalization.None),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                capitalization = KeyboardCapitalization.None,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -476,10 +501,12 @@
     @Test
     fun test_fill_editor_info_capitalization_characters() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(capitalization = KeyboardCapitalization.Characters),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                capitalization = KeyboardCapitalization.Characters,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -495,10 +522,12 @@
     @Test
     fun test_fill_editor_info_capitalization_words() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(capitalization = KeyboardCapitalization.Words),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                capitalization = KeyboardCapitalization.Words,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -514,10 +543,12 @@
     @Test
     fun test_fill_editor_info_capitalization_sentences() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                capitalization = KeyboardCapitalization.Sentences,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done,
+            ),
             >
             >
         )
@@ -533,10 +564,12 @@
     @Test
     fun test_fill_editor_info_capitalization_not_added_when_input_type_is_not_text() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Number,
-            ImeAction.Done,
-            KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                capitalization = KeyboardCapitalization.Sentences,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done,
+            ),
             >
             >
         )
@@ -552,10 +585,12 @@
     @Test
     fun test_fill_editor_info_auto_correct_on() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(autoCorrect = true),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                autoCorrect = true,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -569,10 +604,12 @@
     @Test
     fun test_fill_editor_info_auto_correct_off() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Ascii,
-            ImeAction.Done,
-            KeyboardOptions(autoCorrect = false),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                autoCorrect = false,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
@@ -586,10 +623,12 @@
     @Test
     fun autocorrect_not_added_when_input_type_is_not_text() {
         textInputService.startInput(
-            TextFieldValue(""),
-            KeyboardType.Number,
-            ImeAction.Done,
-            KeyboardOptions(autoCorrect = true),
+            value = TextFieldValue(""),
+            keyboardOptions = KeyboardOptions(
+                autoCorrect = true,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done
+            ),
             >
             >
         )
diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle
index dde8efc..3beca1c 100644
--- a/navigation/navigation-compose/build.gradle
+++ b/navigation/navigation-compose/build.gradle
@@ -34,6 +34,7 @@
 
     implementation(KOTLIN_STDLIB)
     api project(":compose:runtime:runtime")
+    api project(":compose:runtime:runtime-saved-instance-state")
     api project(":compose:ui:ui")
     api "androidx.navigation:navigation-runtime-ktx:2.3.1"
 
diff --git a/test/screenshot/build.gradle b/test/screenshot/build.gradle
index 72f2376..21e4e0a 100644
--- a/test/screenshot/build.gradle
+++ b/test/screenshot/build.gradle
@@ -43,10 +43,4 @@
 androidx {
     name = "AndroidX Library Screenshot Test"
     mavenGroup = LibraryGroups.TESTSCREENSHOT
-}
-
-android {
-    defaultConfig {
-        testInstrumentationRunnerArgument("thisisignored", "thisisignored --no-isolated-storage")
-    }
 }
\ No newline at end of file
diff --git a/test/screenshot/src/main/java/androidx/test/screenshot/ScreenshotTestRule.kt b/test/screenshot/src/main/java/androidx/test/screenshot/ScreenshotTestRule.kt
index 36706d1..341e0b0 100644
--- a/test/screenshot/src/main/java/androidx/test/screenshot/ScreenshotTestRule.kt
+++ b/test/screenshot/src/main/java/androidx/test/screenshot/ScreenshotTestRule.kt
@@ -20,6 +20,7 @@
 import android.graphics.Bitmap
 import android.graphics.BitmapFactory
 import android.os.Build
+import android.os.Bundle
 import androidx.core.os.BuildCompat
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.screenshot.matchers.BitmapMatcher
@@ -82,7 +83,11 @@
     /**
      * Directory on the device that is used to store the output files.
      */
-    val deviceOutputDirectory = File("/sdcard", "androidx_screenshots")
+    val deviceOutputDirectory
+        get() = File(
+            InstrumentationRegistry.getInstrumentation().getContext().externalCacheDir,
+            "androidx_screenshots"
+        )
 
     private val repoRootPathForGoldens = config.repoRootPathForGoldens.trim('/')
     private val pathToGoldensInRepo = config.pathToGoldensInRepo.trim('/')
@@ -90,6 +95,10 @@
     // This is used in CI to identify the files.
     private val resultProtoFileSuffix = "goldResult.textproto"
 
+    // Magic number for an in-progress status report
+    private val bundleStatusInProgress = 2
+    private val bundleKeyPrefix = "androidx_screenshots_"
+
     private lateinit var testIdentifier: String
     private lateinit var deviceId: String
 
@@ -252,20 +261,37 @@
                 "$pathToGoldensInRepo/${goldenIdentifierResolver(goldenIdentifier)}"
             }
 
+        val report = Bundle()
+
         if (status != ScreenshotResultProto.ScreenshotResult.Status.PASSED) {
-            resultProto.currentScreenshotFileName =
-                actual.writeToDevice(OutputFileType.IMAGE_ACTUAL)
+            actual.writeToDevice(OutputFileType.IMAGE_ACTUAL).also {
+                resultProto.currentScreenshotFileName = it.name
+                report.putString(bundleKeyPrefix + OutputFileType.IMAGE_ACTUAL, it.absolutePath)
+            }
             diff?.run {
-                resultProto.diffImageFileName = writeToDevice(OutputFileType.IMAGE_DIFF)
+                writeToDevice(OutputFileType.IMAGE_DIFF).also {
+                    resultProto.diffImageFileName = it.name
+                    report.putString(bundleKeyPrefix + OutputFileType.IMAGE_DIFF, it.absolutePath)
+                }
             }
             expected?.run {
-                resultProto.expectedImageFileName = writeToDevice(OutputFileType.IMAGE_EXPECTED)
+                writeToDevice(OutputFileType.IMAGE_EXPECTED).also {
+                    resultProto.expectedImageFileName = it.name
+                    report.putString(
+                        bundleKeyPrefix + OutputFileType.IMAGE_EXPECTED,
+                        it.absolutePath
+                    )
+                }
             }
         }
 
         writeToDevice(OutputFileType.RESULT_PROTO) {
             it.write(resultProto.build().toString().toByteArray())
+        }.also {
+            report.putString(bundleKeyPrefix + OutputFileType.RESULT_PROTO, it.absolutePath)
         }
+
+        InstrumentationRegistry.getInstrumentation().sendStatus(bundleStatusInProgress, report)
     }
 
     internal fun getPathOnDeviceFor(fileType: OutputFileType): File {
@@ -278,32 +304,34 @@
         return File(deviceOutputDirectory, fileName)
     }
 
-    private fun Bitmap.writeToDevice(fileType: OutputFileType): String {
+    private fun Bitmap.writeToDevice(fileType: OutputFileType): File {
         return writeToDevice(fileType) {
             compress(Bitmap.CompressFormat.PNG, 0 /*ignored for png*/, it)
         }
     }
 
-    private fun writeToDevice(fileType: OutputFileType, writeAction: (FileOutputStream) -> Unit):
-        String {
-            if (!deviceOutputDirectory.exists() && !deviceOutputDirectory.mkdir()) {
-                throw IOException("Could not create folder.")
-            }
-
-            var file = getPathOnDeviceFor(fileType)
-            try {
-                FileOutputStream(file).use {
-                    writeAction(it)
-                }
-            } catch (e: Exception) {
-                throw IOException(
-                    "Could not write file to storage (path: ${file.absolutePath}). " +
-                        " Stacktrace: " + e.stackTrace
-                )
-            }
-            return file.name
+    private fun writeToDevice(
+        fileType: OutputFileType,
+        writeAction: (FileOutputStream) -> Unit
+    ): File {
+        if (!deviceOutputDirectory.exists() && !deviceOutputDirectory.mkdir()) {
+            throw IOException("Could not create folder.")
         }
 
+        var file = getPathOnDeviceFor(fileType)
+        try {
+            FileOutputStream(file).use {
+                writeAction(it)
+            }
+        } catch (e: Exception) {
+            throw IOException(
+                "Could not write file to storage (path: ${file.absolutePath}). " +
+                    " Stacktrace: " + e.stackTrace
+            )
+        }
+        return file
+    }
+
     private fun getDeviceModel(): String {
         var model = android.os.Build.MODEL.toLowerCase()
         arrayOf("phone", "x86", "x64").forEach {