[go: nahoru, domu]

Merge "Add IntRange annotation to int parameters where appropriate" into androidx-main
diff --git a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/JankMetricValidation.kt b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/FrameTimingMetricValidation.kt
similarity index 95%
rename from benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/JankMetricValidation.kt
rename to benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/FrameTimingMetricValidation.kt
index 8d2e9a2..e88aea4 100644
--- a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/JankMetricValidation.kt
+++ b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/FrameTimingMetricValidation.kt
@@ -18,7 +18,7 @@
 
 import android.content.Intent
 import androidx.benchmark.macro.CompilationMode
-import androidx.benchmark.macro.JankMetric
+import androidx.benchmark.macro.FrameTimingMetric
 import androidx.benchmark.macro.MacrobenchmarkConfig
 import androidx.benchmark.macro.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
@@ -36,7 +36,7 @@
 @LargeTest
 @SdkSuppress(minSdkVersion = 29)
 @RunWith(Parameterized::class)
-class JankMetricValidation(
+class FrameTimingMetricValidation(
     private val compilationMode: CompilationMode
 ) {
     @get:Rule
@@ -54,7 +54,7 @@
     fun start() {
         val config = MacrobenchmarkConfig(
             packageName = PACKAGE_NAME,
-            metrics = listOf(JankMetric()),
+            metrics = listOf(FrameTimingMetric()),
             compilationMode = compilationMode,
             iterations = 10
         )
diff --git a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/StartupUtils.kt b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/StartupUtils.kt
index e8c152e..bc58b13 100644
--- a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/StartupUtils.kt
+++ b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/StartupUtils.kt
@@ -48,4 +48,4 @@
     intent.setPackage(TARGET_PACKAGE)
     setupIntent(intent)
     launchIntentAndWait(intent)
-}
\ No newline at end of file
+}
diff --git a/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt b/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
index 2d211f9..50b0812 100644
--- a/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
+++ b/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
@@ -100,10 +100,20 @@
 
 data class MacrobenchmarkConfig(
     val packageName: String,
-    val metrics: List<Metric>,
+    var metrics: List<Metric>,
     val compilationMode: CompilationMode = CompilationMode.SpeedProfile(),
     val iterations: Int
-)
+) {
+    init {
+        val metricSet = metrics.toSet()
+        val hasStartupMetric = metricSet.any { it is StartupTimingMetric }
+        if (hasStartupMetric) {
+            val metrics = metrics.toMutableList()
+            metrics += PerfettoMetric()
+            this.metrics = metrics.toList()
+        }
+    }
+}
 
 /**
  * macrobenchmark test entrypoint, which doesn't depend on JUnit.
@@ -141,24 +151,23 @@
         val metricResults = List(config.iterations) { iteration ->
             setupBlock(scope, isFirstRun)
             isFirstRun = false
-            try {
-                perfettoCollector.start()
-                config.metrics.forEach {
-                    it.start()
+            perfettoCollector.captureTrace(uniqueName, iteration) { tracePath ->
+                try {
+                    config.metrics.forEach {
+                        it.start()
+                    }
+                    measureBlock(scope)
+                } finally {
+                    config.metrics.forEach {
+                        it.stop()
+                    }
                 }
-                measureBlock(scope)
-            } finally {
-                config.metrics.forEach {
-                    it.stop()
-                }
-                perfettoCollector.stop(uniqueName, iteration)
+                config.metrics
+                    // capture list of Map<String,Long> per metric
+                    .map { it.getMetrics(config.packageName, tracePath) }
+                    // merge into one map
+                    .reduce { sum, element -> sum + element }
             }
-
-            config.metrics
-                // capture list of Map<String,Long> per metric
-                .map { it.getMetrics(config.packageName) }
-                // merge into one map
-                .reduce { sum, element -> sum + element }
         }.mergeToMetricResults()
 
         InstrumentationResults.instrumentationReport {
diff --git a/benchmark/macro/src/main/java/androidx/benchmark/macro/Metric.kt b/benchmark/macro/src/main/java/androidx/benchmark/macro/Metric.kt
index aee2877..70aa835 100644
--- a/benchmark/macro/src/main/java/androidx/benchmark/macro/Metric.kt
+++ b/benchmark/macro/src/main/java/androidx/benchmark/macro/Metric.kt
@@ -16,6 +16,9 @@
 
 package androidx.benchmark.macro
 
+import android.util.Log
+import androidx.benchmark.perfetto.PerfettoResultsParser.parseResult
+import androidx.benchmark.perfetto.PerfettoTraceParser
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.UiDevice
 import com.android.helpers.CpuUsageHelper
@@ -31,14 +34,13 @@
     abstract fun start()
 
     abstract fun stop()
-
     /**
      * After stopping, collect metrics
      *
      * TODO: takes package for package level filtering, but probably want a
      *  general config object coming into [start].
      */
-    abstract fun getMetrics(packageName: String): Map<String, Long>
+    abstract fun getMetrics(packageName: String, tracePath: String): Map<String, Long>
 }
 
 class StartupTimingMetric : Metric() {
@@ -56,7 +58,7 @@
         helper.stopCollecting()
     }
 
-    override fun getMetrics(packageName: String): Map<String, Long> {
+    override fun getMetrics(packageName: String, tracePath: String): Map<String, Long> {
         return helper.getMetrics(packageName)
     }
 }
@@ -81,12 +83,12 @@
         helper.stopCollecting()
     }
 
-    override fun getMetrics(packageName: String): Map<String, Long> {
+    override fun getMetrics(packageName: String, tracePath: String): Map<String, Long> {
         return helper.metrics
     }
 }
 
-class JankMetric : Metric() {
+class FrameTimingMetric : Metric() {
     private lateinit var packageName: String
     private val helper = JankCollectionHelper()
 
@@ -146,7 +148,7 @@
         "slow_bmp_upload" to "slowBitmapUploadFrameCount",
         "slow_issue_draw_cmds" to "slowIssueDrawCommandsFrameCount",
         "total_frames" to "totalFrameCount",
-        "janky_frames_percent" to "jankyFramePercent",
+        "janky_frames_percent" to "jankyFramePercent"
     )
 
     /**
@@ -157,10 +159,10 @@
         "frameTime90thPercentileMs",
         "frameTime95thPercentileMs",
         "frameTime99thPercentileMs",
-        "totalFrameCount",
+        "totalFrameCount"
     )
 
-    override fun getMetrics(packageName: String): Map<String, Long> {
+    override fun getMetrics(packageName: String, tracePath: String): Map<String, Long> {
         return helper.metrics
             .map {
                 val prefix = "gfxinfo_${packageName}_"
@@ -181,6 +183,48 @@
 }
 
 /**
+ * Only does startup metrics now. Will need to expand scope.
+ */
+internal class PerfettoMetric : Metric() {
+    private lateinit var packageName: String
+    private lateinit var device: UiDevice
+    private lateinit var parser: PerfettoTraceParser
+
+    override fun configure(config: MacrobenchmarkConfig) {
+        packageName = config.packageName
+        val instrumentation = InstrumentationRegistry.getInstrumentation()
+        device = instrumentation.device()
+        parser = PerfettoTraceParser()
+    }
+
+    override fun start() {
+        parser.copyTraceProcessorShell()
+    }
+
+    override fun stop() {
+    }
+
+    override fun getMetrics(packageName: String, tracePath: String): Map<String, Long> {
+        val path = parser.shellFile?.absolutePath
+        return if (path != null) {
+            // TODO: Construct `METRICS` based on the config.
+            val command = "$path --run-metric $METRICS $tracePath --metrics-output=json"
+            Log.d(TAG, "Executing command $command")
+            val json = device.executeShellCommand(command)
+            Log.d(TAG, "Trace Processor result \n\n $json")
+            parseResult(json, packageName)
+        } else {
+            emptyMap()
+        }
+    }
+
+    companion object {
+        private const val TAG = "PerfettoMetric"
+        private const val METRICS = "android_startup"
+    }
+}
+
+/**
  * Not public, as this needs clarified metric names
  */
 internal class TotalPssMetric : Metric() {
@@ -198,7 +242,7 @@
         helper.stopCollecting()
     }
 
-    override fun getMetrics(packageName: String): Map<String, Long> {
+    override fun getMetrics(packageName: String, tracePath: String): Map<String, Long> {
         return helper.metrics
     }
 }
diff --git a/benchmark/macro/src/main/java/androidx/benchmark/macro/PerfettoCaptureWrapper.kt b/benchmark/macro/src/main/java/androidx/benchmark/macro/PerfettoCaptureWrapper.kt
index 840dee5..39d26a4 100644
--- a/benchmark/macro/src/main/java/androidx/benchmark/macro/PerfettoCaptureWrapper.kt
+++ b/benchmark/macro/src/main/java/androidx/benchmark/macro/PerfettoCaptureWrapper.kt
@@ -19,6 +19,7 @@
 import android.os.Build
 import android.util.Log
 import androidx.benchmark.perfetto.PerfettoCapture
+import androidx.benchmark.perfetto.PerfettoHelper
 import androidx.benchmark.perfetto.destinationPath
 import androidx.benchmark.perfetto.reportAdditionalFileToCopy
 
@@ -27,14 +28,26 @@
  */
 class PerfettoCaptureWrapper {
     private var capture: PerfettoCapture? = null
-
     init {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
             capture = PerfettoCapture()
         }
     }
 
-    fun start(): Boolean {
+    fun <T> captureTrace(
+        benchmarkName: String,
+        iteration: Int,
+        block: (String) -> T
+    ): T {
+        try {
+            start()
+            return block(PerfettoHelper.getPerfettoTmpOutputFilePath())
+        } finally {
+            stop(benchmarkName, iteration)
+        }
+    }
+
+    private fun start(): Boolean {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
             Log.d(TAG, "Recording perfetto trace")
             capture?.start()
@@ -42,19 +55,14 @@
         return true
     }
 
-    fun stop(benchmarkName: String, iteration: Int): Boolean {
+    private fun stop(benchmarkName: String, iteration: Int): Boolean {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
             val iterString = iteration.toString().padStart(3, '0')
             val traceName = "${benchmarkName}_iter$iterString.trace"
-
             val destination = destinationPath(traceName).absolutePath
             capture?.stop(destination)
             reportAdditionalFileToCopy("perfetto_trace_$iterString", destination)
         }
         return true
     }
-
-    companion object {
-        private const val TAG = "PerfettoCollector"
-    }
 }
diff --git a/benchmark/perfetto/build.gradle b/benchmark/perfetto/build.gradle
index 8210bdd..652a512 100644
--- a/benchmark/perfetto/build.gradle
+++ b/benchmark/perfetto/build.gradle
@@ -17,6 +17,7 @@
 import static androidx.build.dependencies.DependenciesKt.*
 import androidx.build.LibraryGroups
 import androidx.build.Publish
+import androidx.build.SupportConfigKt
 
 plugins {
     id("AndroidXPlugin")
@@ -30,6 +31,12 @@
         // lower minSdkVersion to enable optional usage, based on API level.
         minSdkVersion 18
     }
+    sourceSets {
+        main.assets.srcDirs += new File(
+                SupportConfigKt.getPrebuiltsRoot(project),
+                "androidx/traceprocessor/trace_processor_shell"
+        )
+    }
 }
 
 dependencies {
@@ -45,6 +52,7 @@
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
     androidTestImplementation(ANDROIDX_TEST_RUNNER)
 }
+
 androidx {
     name = "Android Benchmark - Perfetto"
     publish = Publish.NONE
diff --git a/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt
index 77e056a..1e95916 100644
--- a/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt
+++ b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt
@@ -16,7 +16,6 @@
 
 package androidx.benchmark.perfetto
 
-import android.content.Context
 import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
 import androidx.test.platform.app.InstrumentationRegistry
@@ -51,16 +50,13 @@
      * TODO: provide configuration options
      */
     fun start() {
-        val context: Context = InstrumentationRegistry.getInstrumentation().context
-
+        val context = InstrumentationRegistry.getInstrumentation().context
         // Write textproto asset to external files dir, so it can be read by shell
         // TODO: use binary proto (which will also give us rooted 28 support)
         val configBytes = context.resources.openRawResource(R.raw.trace_config).readBytes()
         val textProtoFile = File(context.getExternalFilesDir(null), "trace_config.textproto")
-
         try {
             textProtoFile.writeBytes(configBytes)
-
             // Start tracing
             if (!helper.startCollecting(textProtoFile.absolutePath, true)) {
                 // TODO: move internal failures to be exceptions
@@ -83,4 +79,4 @@
             throw IllegalStateException("Unable to store perfetto trace")
         }
     }
-}
\ No newline at end of file
+}
diff --git a/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.java b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.java
index 6060a4d..fa60360 100644
--- a/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.java
+++ b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoHelper.java
@@ -19,7 +19,10 @@
 import android.os.SystemClock;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.uiautomator.UiDevice;
 
@@ -31,9 +34,12 @@
 /**
  * PerfettoHelper is used to start and stop the perfetto tracing and move the
  * output perfetto trace file to destination folder.
+ *
+ * @hide
  */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 @RequiresApi(28)
-class PerfettoHelper {
+public class PerfettoHelper {
     private static final String LOG_TAG = PerfettoHelper.class.getSimpleName();
     // Command to start the perfetto tracing in the background.
     // perfetto -b -c /data/misc/perfetto-traces/trace_config.pb -o
@@ -51,7 +57,8 @@
     // Check if perfetto is stopped every 5 secs.
     private static final long PERFETTO_KILL_WAIT_TIME = 5000;
 
-    private UiDevice mUIDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+    private final UiDevice mUIDevice =
+            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
 
     /**
      * Start the perfetto tracing in background using the given config file.
@@ -64,7 +71,7 @@
      * @param isTextProtoConfig true if the config file is textproto format otherwise false.
      * @return true if trace collection started successfully otherwise return false.
      */
-    public boolean startCollecting(String configFilePath, boolean isTextProtoConfig) {
+    public boolean startCollecting(@Nullable String configFilePath, boolean isTextProtoConfig) {
         if (configFilePath == null || configFilePath.isEmpty()) {
             Log.e(LOG_TAG, "Perfetto config file name is null or empty.");
             return false;
@@ -115,7 +122,7 @@
      * @param destinationFile file to copy the perfetto output trace.
      * @return true if the trace collection is successful otherwise false.
      */
-    public boolean stopCollecting(long waitTimeInMsecs, String destinationFile) {
+    public boolean stopCollecting(long waitTimeInMsecs, @NonNull String destinationFile) {
         // Wait for the dump interval before stopping the trace.
         Log.i(LOG_TAG, String.format(
                 "Waiting for %d msecs before stopping perfetto.", waitTimeInMsecs));
@@ -190,13 +197,22 @@
     }
 
     /**
+     * @return the {@link String} path to the temporary output file used to store the trace file
+     * during collection.
+     */
+    @NonNull
+    public static String getPerfettoTmpOutputFilePath() {
+        return PERFETTO_TMP_OUTPUT_FILE;
+    }
+
+    /**
      * Copy the temporary perfetto trace output file from /data/misc/perfetto-traces/ to given
      * destinationFile.
      *
      * @param destinationFile file to copy the perfetto output trace.
      * @return true if the trace file copied successfully otherwise false.
      */
-    private boolean copyFileOutput(String destinationFile) {
+    private boolean copyFileOutput(@NonNull String destinationFile) {
         Path path = Paths.get(destinationFile);
         String destDirectory = path.getParent().toString();
         // Check if the directory already exists
diff --git a/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoResultsParser.kt b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoResultsParser.kt
new file mode 100644
index 0000000..dc0d611
--- /dev/null
+++ b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoResultsParser.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.perfetto
+
+import org.json.JSONArray
+import org.json.JSONObject
+
+object PerfettoResultsParser {
+    fun parseResult(jsonTrace: String, packageName: String): Map<String, Long> {
+        val map = mutableMapOf<String, Long>()
+        val json = JSONObject(jsonTrace)
+        val androidStartup = json.optJSONObject(ANDROID_STARTUP)
+        if (androidStartup != null) {
+            val startup = androidStartup.optJSONArray(STARTUP)
+            if (startup != null && startup.length() > 0) {
+                parseStartupResult(startup, packageName, map)
+            }
+        }
+        return map
+    }
+
+    private fun parseStartupResult(
+        json: JSONArray,
+        packageName: String,
+        map: MutableMap<String, Long>
+    ) {
+        val length = json.length()
+        for (i in 0 until length) {
+            val startupResult = json.getJSONObject(i)
+            val targetPackageName = startupResult.optString(PACKAGE_NAME)
+            if (packageName == targetPackageName) {
+                val firstFrameMetric = startupResult.optJSONObject(TO_FIRST_FRAME)
+                if (firstFrameMetric != null) {
+                    val duration = firstFrameMetric.optDouble(DUR_MS, 0.0)
+                    map[STARTUP_MS] = duration.toLong()
+                }
+            }
+        }
+    }
+
+    private const val ANDROID_STARTUP = "android_startup"
+    private const val STARTUP = "startup"
+    private const val PACKAGE_NAME = "package_name"
+    private const val TO_FIRST_FRAME = "to_first_frame"
+    private const val DUR_MS = "dur_ms"
+    private const val TIME_ACTIVITY_START = "time_activity_start"
+    private const val TIME_ACTIVITY_RESUME = "time_activity_resume"
+
+    // Metric Keys
+    private const val STARTUP_MS = "perfetto_startupMs"
+}
diff --git a/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoTraceParser.kt b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoTraceParser.kt
new file mode 100644
index 0000000..785be51
--- /dev/null
+++ b/benchmark/perfetto/src/main/java/androidx/benchmark/perfetto/PerfettoTraceParser.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.perfetto
+
+import android.content.Context
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.annotation.RestrictTo
+import androidx.test.platform.app.InstrumentationRegistry
+import java.io.File
+
+/**
+ * Enables parsing perfetto traces on-device on Q+ devices.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@RequiresApi(21)
+class PerfettoTraceParser {
+
+    /**
+     * The actual [File] path to the `trace_processor_shell`.
+     */
+    var shellFile: File? = null
+
+    /**
+     * Copies `trace_processor_shell` and enables parsing of the perfetto trace files.
+     */
+    fun copyTraceProcessorShell() {
+        val instrumentation = InstrumentationRegistry.getInstrumentation()
+        val context: Context = instrumentation.context
+        shellFile = File(context.cacheDir, "trace_processor_shell")
+        // TODO: support other ABIs
+        if (Build.SUPPORTED_64_BIT_ABIS.isEmpty()) {
+            throw IllegalStateException("Unsupported ABI")
+        }
+        // Write the trace_processor_shell to the external directory so we can process
+        // perfetto metrics on device.
+        val shellFile = shellFile
+        if (shellFile != null && !shellFile.exists()) {
+            val created = shellFile.createNewFile()
+            shellFile.setWritable(true)
+            shellFile.setExecutable(true, false)
+            if (!created) {
+                throw IllegalStateException("Unable to create new file $shellFile")
+            }
+            shellFile.outputStream().use {
+                // TODO: Copy the file based on the ABI
+                context.assets.open("trace_processor_shell_aarch64").copyTo(it)
+            }
+        }
+    }
+}
diff --git a/biometric/biometric-ktx/api/current.txt b/biometric/biometric-ktx/api/current.txt
index d2293f0..1342c5a8 100644
--- a/biometric/biometric-ktx/api/current.txt
+++ b/biometric/biometric-ktx/api/current.txt
@@ -1,22 +1,46 @@
 // Signature format: 4.0
 package androidx.biometric.auth {
 
+  public final class AuthPromptErrorException extends java.lang.Exception {
+    ctor public AuthPromptErrorException(int errorCode, CharSequence errorMessage);
+    method public int getErrorCode();
+    method public CharSequence getErrorMessage();
+    property public final int errorCode;
+    property public final CharSequence errorMessage;
+  }
+
+  public final class AuthPromptFailureException extends java.lang.Exception {
+    ctor public AuthPromptFailureException();
+  }
+
   public final class Class2BiometricAuthExtensionsKt {
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class2BiometricAuthPrompt, androidx.biometric.auth.AuthPromptHost host, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2Biometrics(androidx.fragment.app.FragmentActivity, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2Biometrics(androidx.fragment.app.Fragment, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricAuthentication(androidx.fragment.app.FragmentActivity, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricAuthentication(androidx.fragment.app.Fragment, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
 
   public final class Class2BiometricOrCredentialAuthExtensionsKt {
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class2BiometricOrCredentialAuthPrompt, androidx.biometric.auth.AuthPromptHost host, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2BiometricsOrCredentials(androidx.fragment.app.FragmentActivity, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2BiometricsOrCredentials(androidx.fragment.app.Fragment, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricOrCredentialAuthentication(androidx.fragment.app.FragmentActivity, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricOrCredentialAuthentication(androidx.fragment.app.Fragment, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
 
   public final class Class3BiometricAuthExtensionsKt {
-    method public static androidx.biometric.auth.AuthPrompt startClass3BiometricAuthentication(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
-    method public static androidx.biometric.auth.AuthPrompt startClass3BiometricAuthentication(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class3BiometricAuthPrompt, androidx.biometric.auth.AuthPromptHost host, androidx.biometric.BiometricPrompt.CryptoObject? crypto, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static androidx.biometric.auth.AuthPrompt authenticateWithClass3Biometrics(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticateWithClass3Biometrics(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static androidx.biometric.auth.AuthPrompt authenticateWithClass3Biometrics(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticateWithClass3Biometrics(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
   }
 
   public final class Class3BiometricOrCredentialAuthExtensionsKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticate(androidx.biometric.auth.Class3BiometricOrCredentialAuthPrompt, androidx.biometric.auth.AuthPromptHost host, androidx.biometric.BiometricPrompt.CryptoObject? crypto, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticateWithClass3BiometricsOrCredentials(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticateWithClass3BiometricsOrCredentials(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method @RequiresApi(android.os.Build.VERSION_CODES.R) public static androidx.biometric.auth.AuthPrompt startClass3BiometricOrCredentialAuthentication(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method @RequiresApi(android.os.Build.VERSION_CODES.R) public static androidx.biometric.auth.AuthPrompt startClass3BiometricOrCredentialAuthentication(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
diff --git a/biometric/biometric-ktx/api/public_plus_experimental_current.txt b/biometric/biometric-ktx/api/public_plus_experimental_current.txt
index d2293f0..1342c5a8 100644
--- a/biometric/biometric-ktx/api/public_plus_experimental_current.txt
+++ b/biometric/biometric-ktx/api/public_plus_experimental_current.txt
@@ -1,22 +1,46 @@
 // Signature format: 4.0
 package androidx.biometric.auth {
 
+  public final class AuthPromptErrorException extends java.lang.Exception {
+    ctor public AuthPromptErrorException(int errorCode, CharSequence errorMessage);
+    method public int getErrorCode();
+    method public CharSequence getErrorMessage();
+    property public final int errorCode;
+    property public final CharSequence errorMessage;
+  }
+
+  public final class AuthPromptFailureException extends java.lang.Exception {
+    ctor public AuthPromptFailureException();
+  }
+
   public final class Class2BiometricAuthExtensionsKt {
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class2BiometricAuthPrompt, androidx.biometric.auth.AuthPromptHost host, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2Biometrics(androidx.fragment.app.FragmentActivity, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2Biometrics(androidx.fragment.app.Fragment, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricAuthentication(androidx.fragment.app.FragmentActivity, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricAuthentication(androidx.fragment.app.Fragment, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
 
   public final class Class2BiometricOrCredentialAuthExtensionsKt {
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class2BiometricOrCredentialAuthPrompt, androidx.biometric.auth.AuthPromptHost host, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2BiometricsOrCredentials(androidx.fragment.app.FragmentActivity, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2BiometricsOrCredentials(androidx.fragment.app.Fragment, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricOrCredentialAuthentication(androidx.fragment.app.FragmentActivity, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricOrCredentialAuthentication(androidx.fragment.app.Fragment, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
 
   public final class Class3BiometricAuthExtensionsKt {
-    method public static androidx.biometric.auth.AuthPrompt startClass3BiometricAuthentication(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
-    method public static androidx.biometric.auth.AuthPrompt startClass3BiometricAuthentication(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class3BiometricAuthPrompt, androidx.biometric.auth.AuthPromptHost host, androidx.biometric.BiometricPrompt.CryptoObject? crypto, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static androidx.biometric.auth.AuthPrompt authenticateWithClass3Biometrics(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticateWithClass3Biometrics(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static androidx.biometric.auth.AuthPrompt authenticateWithClass3Biometrics(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticateWithClass3Biometrics(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
   }
 
   public final class Class3BiometricOrCredentialAuthExtensionsKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticate(androidx.biometric.auth.Class3BiometricOrCredentialAuthPrompt, androidx.biometric.auth.AuthPromptHost host, androidx.biometric.BiometricPrompt.CryptoObject? crypto, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticateWithClass3BiometricsOrCredentials(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticateWithClass3BiometricsOrCredentials(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method @RequiresApi(android.os.Build.VERSION_CODES.R) public static androidx.biometric.auth.AuthPrompt startClass3BiometricOrCredentialAuthentication(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method @RequiresApi(android.os.Build.VERSION_CODES.R) public static androidx.biometric.auth.AuthPrompt startClass3BiometricOrCredentialAuthentication(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
diff --git a/biometric/biometric-ktx/api/restricted_current.txt b/biometric/biometric-ktx/api/restricted_current.txt
index d2293f0..1342c5a8 100644
--- a/biometric/biometric-ktx/api/restricted_current.txt
+++ b/biometric/biometric-ktx/api/restricted_current.txt
@@ -1,22 +1,46 @@
 // Signature format: 4.0
 package androidx.biometric.auth {
 
+  public final class AuthPromptErrorException extends java.lang.Exception {
+    ctor public AuthPromptErrorException(int errorCode, CharSequence errorMessage);
+    method public int getErrorCode();
+    method public CharSequence getErrorMessage();
+    property public final int errorCode;
+    property public final CharSequence errorMessage;
+  }
+
+  public final class AuthPromptFailureException extends java.lang.Exception {
+    ctor public AuthPromptFailureException();
+  }
+
   public final class Class2BiometricAuthExtensionsKt {
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class2BiometricAuthPrompt, androidx.biometric.auth.AuthPromptHost host, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2Biometrics(androidx.fragment.app.FragmentActivity, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2Biometrics(androidx.fragment.app.Fragment, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricAuthentication(androidx.fragment.app.FragmentActivity, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricAuthentication(androidx.fragment.app.Fragment, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
 
   public final class Class2BiometricOrCredentialAuthExtensionsKt {
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class2BiometricOrCredentialAuthPrompt, androidx.biometric.auth.AuthPromptHost host, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2BiometricsOrCredentials(androidx.fragment.app.FragmentActivity, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static suspend Object? authenticateWithClass2BiometricsOrCredentials(androidx.fragment.app.Fragment, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricOrCredentialAuthentication(androidx.fragment.app.FragmentActivity, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method public static androidx.biometric.auth.AuthPrompt startClass2BiometricOrCredentialAuthentication(androidx.fragment.app.Fragment, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
 
   public final class Class3BiometricAuthExtensionsKt {
-    method public static androidx.biometric.auth.AuthPrompt startClass3BiometricAuthentication(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
-    method public static androidx.biometric.auth.AuthPrompt startClass3BiometricAuthentication(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticate(androidx.biometric.auth.Class3BiometricAuthPrompt, androidx.biometric.auth.AuthPromptHost host, androidx.biometric.BiometricPrompt.CryptoObject? crypto, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static androidx.biometric.auth.AuthPrompt authenticateWithClass3Biometrics(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticateWithClass3Biometrics(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method public static androidx.biometric.auth.AuthPrompt authenticateWithClass3Biometrics(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
+    method public static suspend Object? authenticateWithClass3Biometrics(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, CharSequence negativeButtonText, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
   }
 
   public final class Class3BiometricOrCredentialAuthExtensionsKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticate(androidx.biometric.auth.Class3BiometricOrCredentialAuthPrompt, androidx.biometric.auth.AuthPromptHost host, androidx.biometric.BiometricPrompt.CryptoObject? crypto, kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticateWithClass3BiometricsOrCredentials(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
+    method @RequiresApi(android.os.Build.VERSION_CODES.R) public static suspend Object? authenticateWithClass3BiometricsOrCredentials(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional kotlin.coroutines.Continuation<? super androidx.biometric.BiometricPrompt.AuthenticationResult> p);
     method @RequiresApi(android.os.Build.VERSION_CODES.R) public static androidx.biometric.auth.AuthPrompt startClass3BiometricOrCredentialAuthentication(androidx.fragment.app.FragmentActivity, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
     method @RequiresApi(android.os.Build.VERSION_CODES.R) public static androidx.biometric.auth.AuthPrompt startClass3BiometricOrCredentialAuthentication(androidx.fragment.app.Fragment, androidx.biometric.BiometricPrompt.CryptoObject? crypto, CharSequence title, optional CharSequence? subtitle, optional CharSequence? description, optional boolean confirmationRequired, optional java.util.concurrent.Executor? executor, androidx.biometric.auth.AuthPromptCallback callback);
   }
diff --git a/biometric/biometric-ktx/build.gradle b/biometric/biometric-ktx/build.gradle
index 570ffa1..4dc85dc 100755
--- a/biometric/biometric-ktx/build.gradle
+++ b/biometric/biometric-ktx/build.gradle
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-import static androidx.build.dependencies.DependenciesKt.*
+
 import androidx.build.LibraryGroups
 import androidx.build.Publish
 
+import static androidx.build.dependencies.DependenciesKt.getKOTLIN_COROUTINES_CORE
+import static androidx.build.dependencies.DependenciesKt.getKOTLIN_STDLIB
+
 
 plugins {
     id("AndroidXPlugin")
@@ -27,6 +30,7 @@
 
 dependencies {
     api(KOTLIN_STDLIB)
+    api(KOTLIN_COROUTINES_CORE)
     api(project(":biometric:biometric"))
 }
 
@@ -36,4 +40,4 @@
     mavenGroup = LibraryGroups.BIOMETRIC
     inceptionYear = "2020"
     description = "Kotlin extensions for the Biometric Library."
-}
\ No newline at end of file
+}
diff --git a/biometric/biometric-ktx/samples/build.gradle b/biometric/biometric-ktx/samples/build.gradle
new file mode 100644
index 0000000..bf95a76
--- /dev/null
+++ b/biometric/biometric-ktx/samples/build.gradle
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryType
+import androidx.build.LibraryVersions
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("kotlin-android")
+}
+
+dependencies {
+    compileOnly(project(":annotation:annotation-sampled"))
+    implementation(project(":biometric:biometric-ktx"))
+}
+
+androidx {
+    name = "AndroidX Biometric Samples"
+    type = LibraryType.SAMPLES
+    mavenGroup = LibraryGroups.BIOMETRIC
+    inceptionYear = "2021"
+    description = "Contains the sample code for the AndroidX Biometric library"
+}
diff --git a/biometric/biometric-ktx/samples/lint-baseline.xml b/biometric/biometric-ktx/samples/lint-baseline.xml
new file mode 100644
index 0000000..8f1aa4b
--- /dev/null
+++ b/biometric/biometric-ktx/samples/lint-baseline.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.2.0-beta02" client="gradle" variant="debug" version="4.2.0-beta02">
+
+</issues>
diff --git a/biometric/biometric-ktx/samples/src/main/AndroidManifest.xml b/biometric/biometric-ktx/samples/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1dacecc
--- /dev/null
+++ b/biometric/biometric-ktx/samples/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.biometric.samples"/>
diff --git a/biometric/biometric-ktx/samples/src/main/java/androidx/biometric/samples/auth/CoroutineSamples.kt b/biometric/biometric-ktx/samples/src/main/java/androidx/biometric/samples/auth/CoroutineSamples.kt
new file mode 100644
index 0000000..4b7aeed
--- /dev/null
+++ b/biometric/biometric-ktx/samples/src/main/java/androidx/biometric/samples/auth/CoroutineSamples.kt
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.biometric.samples.auth
+
+import android.security.keystore.KeyGenParameterSpec
+import android.security.keystore.KeyProperties
+import androidx.annotation.Sampled
+import androidx.biometric.BiometricPrompt
+import androidx.biometric.auth.AuthPromptErrorException
+import androidx.biometric.auth.AuthPromptFailureException
+import androidx.biometric.auth.AuthPromptHost
+import androidx.biometric.auth.Class2BiometricAuthPrompt
+import androidx.biometric.auth.Class2BiometricOrCredentialAuthPrompt
+import androidx.biometric.auth.Class3BiometricAuthPrompt
+import androidx.biometric.auth.Class3BiometricOrCredentialAuthPrompt
+import androidx.biometric.auth.authenticate
+import androidx.fragment.app.Fragment
+import java.nio.charset.Charset
+import java.security.KeyStore
+import javax.crypto.Cipher
+import javax.crypto.KeyGenerator
+import javax.crypto.SecretKey
+
+// Stubbed definitions for samples
+private const val KEYSTORE_INSTANCE = "AndroidKeyStore"
+private const val KEY_NAME = "mySecretKey"
+private const val title = ""
+private const val subtitle = ""
+private const val description = ""
+private const val negativeButtonText = ""
+private fun sendEncryptedPayload(payload: ByteArray?): ByteArray? = payload
+
+@Sampled
+suspend fun Fragment.class2BiometricAuth() {
+    val payload = "A message to encrypt".toByteArray(Charset.defaultCharset())
+
+    // Construct AuthPrompt with localized Strings to be displayed to UI.
+    val authPrompt = Class2BiometricAuthPrompt.Builder(title, negativeButtonText).apply {
+        setSubtitle(subtitle)
+        setDescription(description)
+        setConfirmationRequired(true)
+    }.build()
+
+    try {
+        val authResult = authPrompt.authenticate(AuthPromptHost(this))
+
+        // Encrypt a payload using the result of crypto-based auth.
+        val encryptedPayload = authResult.cryptoObject?.cipher?.doFinal(payload)
+
+        // Use the encrypted payload somewhere interesting.
+        sendEncryptedPayload(encryptedPayload)
+    } catch (e: AuthPromptErrorException) {
+        // Handle irrecoverable error during authentication.
+        // Possible values for AuthPromptErrorException.errorCode are listed in the @IntDef,
+        // androidx.biometric.BiometricPrompt.AuthenticationError.
+    } catch (e: AuthPromptFailureException) {
+        // Handle auth failure due biometric credentials being rejected.
+    }
+}
+
+@Sampled
+suspend fun Fragment.class2BiometricOrCredentialAuth() {
+    val payload = "A message to encrypt".toByteArray(Charset.defaultCharset())
+
+    // Construct AuthPrompt with localized Strings to be displayed to UI.
+    val authPrompt = Class2BiometricOrCredentialAuthPrompt.Builder(title).apply {
+        setSubtitle(subtitle)
+        setDescription(description)
+        setConfirmationRequired(true)
+    }.build()
+
+    try {
+        val authResult = authPrompt.authenticate(AuthPromptHost(this))
+
+        // Encrypt a payload using the result of crypto-based auth.
+        val encryptedPayload = authResult.cryptoObject?.cipher?.doFinal(payload)
+
+        // Use the encrypted payload somewhere interesting.
+        sendEncryptedPayload(encryptedPayload)
+    } catch (e: AuthPromptErrorException) {
+        // Handle irrecoverable error during authentication.
+        // Possible values for AuthPromptErrorException.errorCode are listed in the @IntDef,
+        // androidx.biometric.BiometricPrompt.AuthenticationError.
+    } catch (e: AuthPromptFailureException) {
+        // Handle auth failure due biometric credentials being rejected.
+    }
+}
+
+@Sampled
+@Suppress("UnsafeNewApiCall", "NewApi")
+suspend fun Fragment.class3BiometricAuth() {
+    // To use Class3 authentication, we need to create a CryptoObject.
+    // First create a spec for the key to be generated.
+    val keyPurpose = KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
+    val keySpec = KeyGenParameterSpec.Builder(KEY_NAME, keyPurpose).apply {
+        setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+        setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+        setUserAuthenticationRequired(true)
+
+        // Require authentication for each use of the key.
+        val timeout = 0
+        // Set the key type according to the allowed auth types.
+        val keyType =
+            KeyProperties.AUTH_BIOMETRIC_STRONG or KeyProperties.AUTH_DEVICE_CREDENTIAL
+        setUserAuthenticationParameters(timeout, keyType)
+    }.build()
+
+    // Generate and store the key in the Android keystore.
+    KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_INSTANCE).run {
+        init(keySpec)
+        generateKey()
+    }
+
+    // Prepare the crypto object to use for authentication.
+    val cipher = Cipher.getInstance(
+        "${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/" +
+            KeyProperties.ENCRYPTION_PADDING_PKCS7
+    ).apply {
+        val keyStore = KeyStore.getInstance(KEYSTORE_INSTANCE).apply { load(null) }
+        init(Cipher.ENCRYPT_MODE, keyStore.getKey(KEY_NAME, null) as SecretKey)
+    }
+
+    val cryptoObject = BiometricPrompt.CryptoObject(cipher)
+    val payload = "A message to encrypt".toByteArray(Charset.defaultCharset())
+
+    // Construct AuthPrompt with localized Strings to be displayed to UI.
+    val authPrompt = Class3BiometricAuthPrompt.Builder(title, negativeButtonText).apply {
+        setSubtitle(subtitle)
+        setDescription(description)
+        setConfirmationRequired(true)
+    }.build()
+
+    try {
+        val authResult = authPrompt.authenticate(AuthPromptHost(this), cryptoObject)
+
+        // Encrypt a payload using the result of crypto-based auth.
+        val encryptedPayload = authResult.cryptoObject?.cipher?.doFinal(payload)
+
+        // Use the encrypted payload somewhere interesting.
+        sendEncryptedPayload(encryptedPayload)
+    } catch (e: AuthPromptErrorException) {
+        // Handle irrecoverable error during authentication.
+        // Possible values for AuthPromptErrorException.errorCode are listed in the @IntDef,
+        // androidx.biometric.BiometricPrompt.AuthenticationError.
+    } catch (e: AuthPromptFailureException) {
+        // Handle auth failure due biometric credentials being rejected.
+    }
+}
+
+@Sampled
+@Suppress("UnsafeNewApiCall", "NewApi")
+suspend fun Fragment.class3BiometricOrCredentialAuth() {
+    // To use Class3 authentication, we need to create a CryptoObject.
+    // First create a spec for the key to be generated.
+    val keyPurpose = KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
+    val keySpec = KeyGenParameterSpec.Builder(KEY_NAME, keyPurpose).apply {
+        setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+        setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+        setUserAuthenticationRequired(true)
+
+        // Require authentication for each use of the key.
+        val timeout = 0
+        // Set the key type according to the allowed auth types.
+        val keyType =
+            KeyProperties.AUTH_BIOMETRIC_STRONG or KeyProperties.AUTH_DEVICE_CREDENTIAL
+        setUserAuthenticationParameters(timeout, keyType)
+    }.build()
+
+    // Generate and store the key in the Android keystore.
+    KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_INSTANCE).run {
+        init(keySpec)
+        generateKey()
+    }
+
+    // Prepare the crypto object to use for authentication.
+    val cipher = Cipher.getInstance(
+        "${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/" +
+            KeyProperties.ENCRYPTION_PADDING_PKCS7
+    ).apply {
+        val keyStore = KeyStore.getInstance(KEYSTORE_INSTANCE).apply { load(null) }
+        init(Cipher.ENCRYPT_MODE, keyStore.getKey(KEY_NAME, null) as SecretKey)
+    }
+
+    val cryptoObject = BiometricPrompt.CryptoObject(cipher)
+    val payload = "A message to encrypt".toByteArray(Charset.defaultCharset())
+
+    // Construct AuthPrompt with localized Strings to be displayed to UI.
+    val authPrompt = Class3BiometricOrCredentialAuthPrompt.Builder(title).apply {
+        setSubtitle(subtitle)
+        setDescription(description)
+        setConfirmationRequired(true)
+    }.build()
+
+    try {
+        val authResult = authPrompt.authenticate(AuthPromptHost(this), cryptoObject)
+
+        // Encrypt a payload using the result of crypto-based auth.
+        val encryptedPayload = authResult.cryptoObject?.cipher?.doFinal(payload)
+
+        // Use the encrypted payload somewhere interesting.
+        sendEncryptedPayload(encryptedPayload)
+    } catch (e: AuthPromptErrorException) {
+        // Handle irrecoverable error during authentication.
+        // Possible values for AuthPromptErrorException.errorCode are listed in the @IntDef,
+        // androidx.biometric.BiometricPrompt.AuthenticationError.
+    } catch (e: AuthPromptFailureException) {
+        // Handle auth failure due biometric credentials being rejected.
+    }
+}
diff --git a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/AuthPromptErrorException.kt b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/AuthPromptErrorException.kt
new file mode 100644
index 0000000..c1daef7
--- /dev/null
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/AuthPromptErrorException.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.biometric.auth
+/**
+ * Thrown when an unrecoverable error has been encountered and authentication has stopped.
+ *
+ * @param errorCode An integer ID associated with the error.
+ * @param errorMessage A human-readable string that describes the error.
+ */
+public class AuthPromptErrorException(
+    public val errorCode: Int,
+    public val errorMessage: CharSequence
+) : Exception(errorMessage.toString())
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.java b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/AuthPromptFailureException.kt
similarity index 68%
copy from navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.java
copy to biometric/biometric-ktx/src/main/java/androidx/biometric/auth/AuthPromptFailureException.kt
index f9f0fbb..6a1c34e 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.java
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/AuthPromptFailureException.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The Android Open Source Project
+ * 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.
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.navigation;
+package androidx.biometric.auth
 
 /**
- * An interface marking generated Args classes.
+ * Thrown when an authentication attempt by the user has been rejected, e.g., the user's
+ * biometrics were not recognized.
  */
-public interface NavArgs {
-}
+public class AuthPromptFailureException : Exception()
diff --git a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricAuthExtensions.kt b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricAuthExtensions.kt
index 4d67b8c..4c43052 100755
--- a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricAuthExtensions.kt
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricAuthExtensions.kt
@@ -15,11 +15,44 @@
  */
 package androidx.biometric.auth
 
+import androidx.biometric.BiometricPrompt.AuthenticationResult
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
+import kotlinx.coroutines.suspendCancellableCoroutine
 import java.util.concurrent.Executor
 
 /**
+ * Shows an authentication prompt to the user.
+ *
+ * @param host A wrapper for the component that will host the prompt.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class2BiometricAuthPrompt.authenticate(AuthPromptHost, AuthPromptCallback)
+ *
+ * @sample androidx.biometric.samples.auth.class2BiometricAuth
+ */
+public suspend fun Class2BiometricAuthPrompt.authenticate(
+    host: AuthPromptHost,
+): AuthenticationResult {
+    return suspendCancellableCoroutine { continuation ->
+        val authPrompt = startAuthentication(
+            host,
+            Runnable::run,
+            CoroutineAuthPromptCallback(continuation)
+        )
+
+        continuation.invokeOnCancellation {
+            authPrompt.cancelAuthentication()
+        }
+    }
+}
+
+/**
  * Prompts the user to authenticate with a **Class 2** biometric (e.g. fingerprint, face, or iris).
  *
  * Note that **Class 3** biometrics are guaranteed to meet the requirements for **Class 2** and thus
@@ -68,6 +101,44 @@
  * @param subtitle An optional subtitle to be displayed on the prompt.
  * @param description An optional description to be displayed on the prompt.
  * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class2BiometricAuthPrompt
+ */
+public suspend fun FragmentActivity.authenticateWithClass2Biometrics(
+    title: CharSequence,
+    negativeButtonText: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass2BiometricAuthPrompt(
+        title,
+        negativeButtonText,
+        subtitle,
+        description,
+        confirmationRequired,
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this))
+}
+
+/**
+ * Prompts the user to authenticate with a **Class 2** biometric (e.g. fingerprint, face, or iris).
+ *
+ * Note that **Class 3** biometrics are guaranteed to meet the requirements for **Class 2** and thus
+ * will also be accepted.
+ *
+ * @param title The title to be displayed on the prompt.
+ * @param negativeButtonText The label for the negative button on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
  * @param executor An executor for [callback] methods. If `null`, these will run on the main thread.
  * @param callback The object that will receive and process authentication events.
  * @return An [AuthPrompt] handle to the shown prompt.
@@ -96,6 +167,61 @@
 }
 
 /**
+ * Prompts the user to authenticate with a **Class 2** biometric (e.g. fingerprint, face, or iris).
+ *
+ * Note that **Class 3** biometrics are guaranteed to meet the requirements for **Class 2** and thus
+ * will also be accepted.
+ *
+ * @param title The title to be displayed on the prompt.
+ * @param negativeButtonText The label for the negative button on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class2BiometricAuthPrompt
+ */
+public suspend fun Fragment.authenticateWithClass2Biometrics(
+    title: CharSequence,
+    negativeButtonText: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass2BiometricAuthPrompt(
+        title,
+        negativeButtonText,
+        subtitle,
+        description,
+        confirmationRequired,
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this))
+}
+
+/**
+ * Creates a [Class2BiometricAuthPrompt] with the given parameters.
+ */
+private fun buildClass2BiometricAuthPrompt(
+    title: CharSequence,
+    negativeButtonText: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): Class2BiometricAuthPrompt = Class2BiometricAuthPrompt.Builder(title, negativeButtonText)
+    .apply {
+        subtitle?.let { setSubtitle(it) }
+        description?.let { setDescription(it) }
+        setConfirmationRequired(confirmationRequired)
+    }
+    .build()
+
+/**
  * Creates a [Class2BiometricAuthPrompt] with the given parameters and starts authentication.
  */
 private fun startClass2BiometricAuthenticationInternal(
@@ -108,15 +234,17 @@
     executor: Executor? = null,
     callback: AuthPromptCallback
 ): AuthPrompt {
-    val prompt = Class2BiometricAuthPrompt.Builder(title, negativeButtonText).apply {
-        subtitle?.let { setSubtitle(it) }
-        description?.let { setDescription(it) }
-        setConfirmationRequired(confirmationRequired)
-    }.build()
+    val prompt = buildClass2BiometricAuthPrompt(
+        title,
+        negativeButtonText,
+        subtitle,
+        description,
+        confirmationRequired
+    )
 
     return if (executor == null) {
         prompt.startAuthentication(host, callback)
     } else {
         prompt.startAuthentication(host, executor, callback)
     }
-}
\ No newline at end of file
+}
diff --git a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricOrCredentialAuthExtensions.kt b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricOrCredentialAuthExtensions.kt
index 0b3802f..8c772e3 100755
--- a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricOrCredentialAuthExtensions.kt
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class2BiometricOrCredentialAuthExtensions.kt
@@ -15,11 +15,47 @@
  */
 package androidx.biometric.auth
 
+import androidx.biometric.BiometricPrompt.AuthenticationResult
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
+import kotlinx.coroutines.suspendCancellableCoroutine
 import java.util.concurrent.Executor
 
 /**
+ * Shows an authentication prompt to the user.
+ *
+ * @param host A wrapper for the component that will host the prompt.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class2BiometricOrCredentialAuthPrompt.authenticate(
+ *     AuthPromptHost,
+ *     AuthPromptCallback
+ * )
+ *
+ * @sample androidx.biometric.samples.auth.class2BiometricOrCredentialAuth
+ */
+public suspend fun Class2BiometricOrCredentialAuthPrompt.authenticate(
+    host: AuthPromptHost,
+): AuthenticationResult {
+    return suspendCancellableCoroutine { continuation ->
+        val authPrompt = startAuthentication(
+            host,
+            Runnable::run,
+            CoroutineAuthPromptCallback(continuation)
+        )
+
+        continuation.invokeOnCancellation {
+            authPrompt.cancelAuthentication()
+        }
+    }
+}
+
+/**
  * Prompts the user to authenticate with a **Class 2** biometric (e.g. fingerprint, face, or iris)
  * or the screen lock credential (i.e. PIN, pattern, or password) for the device.
  *
@@ -66,6 +102,42 @@
  * @param subtitle An optional subtitle to be displayed on the prompt.
  * @param description An optional description to be displayed on the prompt.
  * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class2BiometricOrCredentialAuthPrompt
+ */
+public suspend fun FragmentActivity.authenticateWithClass2BiometricsOrCredentials(
+    title: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass2BiometricOrCredentialAuthPrompt(
+        title,
+        subtitle,
+        description,
+        confirmationRequired,
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this))
+}
+
+/**
+ * Prompts the user to authenticate with a **Class 2** biometric (e.g. fingerprint, face, or iris)
+ * or the screen lock credential (i.e. PIN, pattern, or password) for the device.
+ *
+ * Note that **Class 3** biometrics are guaranteed to meet the requirements for **Class 2** and thus
+ * will also be accepted.
+ *
+ * @param title The title to be displayed on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
  * @param executor An executor for [callback] methods. If `null`, these will run on the main thread.
  * @param callback The object that will receive and process authentication events.
  * @return An [AuthPrompt] handle to the shown prompt.
@@ -92,6 +164,57 @@
 }
 
 /**
+ * Prompts the user to authenticate with a **Class 2** biometric (e.g. fingerprint, face, or iris)
+ * or the screen lock credential (i.e. PIN, pattern, or password) for the device.
+ *
+ * Note that **Class 3** biometrics are guaranteed to meet the requirements for **Class 2** and thus
+ * will also be accepted.
+ *
+ * @param title The title to be displayed on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ * @return An [AuthPrompt] handle to the shown prompt.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class2BiometricOrCredentialAuthPrompt
+ */
+public suspend fun Fragment.authenticateWithClass2BiometricsOrCredentials(
+    title: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass2BiometricOrCredentialAuthPrompt(
+        title,
+        subtitle,
+        description,
+        confirmationRequired,
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this))
+}
+
+/**
+ * Creates a [Class2BiometricOrCredentialAuthPrompt] with the given parameters.
+ */
+private fun buildClass2BiometricOrCredentialAuthPrompt(
+    title: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): Class2BiometricOrCredentialAuthPrompt = Class2BiometricOrCredentialAuthPrompt.Builder(title)
+    .apply {
+        subtitle?.let { setSubtitle(it) }
+        description?.let { setDescription(it) }
+        setConfirmationRequired(confirmationRequired)
+    }
+    .build()
+
+/**
  * Creates a [Class2BiometricOrCredentialAuthPrompt] with the given parameters and starts
  * authentication.
  */
@@ -104,15 +227,16 @@
     executor: Executor? = null,
     callback: AuthPromptCallback
 ): AuthPrompt {
-    val prompt = Class2BiometricOrCredentialAuthPrompt.Builder(title).apply {
-        subtitle?.let { setSubtitle(it) }
-        description?.let { setDescription(it) }
-        setConfirmationRequired(confirmationRequired)
-    }.build()
+    val prompt = buildClass2BiometricOrCredentialAuthPrompt(
+        title,
+        subtitle,
+        description,
+        confirmationRequired,
+    )
 
     return if (executor == null) {
         prompt.startAuthentication(host, callback)
     } else {
         prompt.startAuthentication(host, executor, callback)
     }
-}
\ No newline at end of file
+}
diff --git a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricAuthExtensions.kt b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricAuthExtensions.kt
index cd7a639..0e24d45 100755
--- a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricAuthExtensions.kt
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricAuthExtensions.kt
@@ -15,12 +15,48 @@
  */
 package androidx.biometric.auth
 
-import androidx.biometric.BiometricPrompt
+import androidx.biometric.BiometricPrompt.AuthenticationResult
+import androidx.biometric.BiometricPrompt.CryptoObject
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
+import kotlinx.coroutines.suspendCancellableCoroutine
 import java.util.concurrent.Executor
 
 /**
+ * Shows an authentication prompt to the user.
+ *
+ * @param host A wrapper for the component that will host the prompt.
+ * @param crypto A cryptographic object to be associated with this authentication.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class3BiometricAuthPrompt.authenticate(AuthPromptHost, AuthPromptCallback)
+ *
+ * @sample androidx.biometric.samples.auth.class3BiometricAuth
+ */
+public suspend fun Class3BiometricAuthPrompt.authenticate(
+    host: AuthPromptHost,
+    crypto: CryptoObject?,
+): AuthenticationResult {
+    return suspendCancellableCoroutine { continuation ->
+        val authPrompt = startAuthentication(
+            host,
+            crypto,
+            Runnable::run,
+            CoroutineAuthPromptCallback(continuation)
+        )
+
+        continuation.invokeOnCancellation {
+            authPrompt.cancelAuthentication()
+        }
+    }
+}
+
+/**
  * Prompts the user to authenticate with a **Class 3** biometric (e.g. fingerprint, face, or iris).
  *
  * @param crypto A cryptographic object to be associated with this authentication.
@@ -35,8 +71,8 @@
  *
  * @see Class3BiometricAuthPrompt
  */
-public fun FragmentActivity.startClass3BiometricAuthentication(
-    crypto: BiometricPrompt.CryptoObject?,
+public fun FragmentActivity.authenticateWithClass3Biometrics(
+    crypto: CryptoObject?,
     title: CharSequence,
     negativeButtonText: CharSequence,
     subtitle: CharSequence? = null,
@@ -67,14 +103,51 @@
  * @param subtitle An optional subtitle to be displayed on the prompt.
  * @param description An optional description to be displayed on the prompt.
  * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class3BiometricAuthPrompt
+ */
+public suspend fun FragmentActivity.authenticateWithClass3Biometrics(
+    crypto: CryptoObject?,
+    title: CharSequence,
+    negativeButtonText: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass3BiometricAuthPrompt(
+        title,
+        negativeButtonText,
+        subtitle,
+        description,
+        confirmationRequired
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this), crypto)
+}
+
+/**
+ * Prompts the user to authenticate with a **Class 3** biometric (e.g. fingerprint, face, or iris).
+ *
+ * @param crypto A cryptographic object to be associated with this authentication.
+ * @param title The title to be displayed on the prompt.
+ * @param negativeButtonText The label for the negative button on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
  * @param executor An executor for [callback] methods. If `null`, these will run on the main thread.
  * @param callback The object that will receive and process authentication events.
  * @return An [AuthPrompt] handle to the shown prompt.
  *
  * @see Class3BiometricAuthPrompt
  */
-public fun Fragment.startClass3BiometricAuthentication(
-    crypto: BiometricPrompt.CryptoObject?,
+public fun Fragment.authenticateWithClass3Biometrics(
+    crypto: CryptoObject?,
     title: CharSequence,
     negativeButtonText: CharSequence,
     subtitle: CharSequence? = null,
@@ -97,11 +170,65 @@
 }
 
 /**
+ * Prompts the user to authenticate with a **Class 3** biometric (e.g. fingerprint, face, or iris).
+ *
+ * @param crypto A cryptographic object to be associated with this authentication.
+ * @param title The title to be displayed on the prompt.
+ * @param negativeButtonText The label for the negative button on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class3BiometricAuthPrompt
+ */
+public suspend fun Fragment.authenticateWithClass3Biometrics(
+    crypto: CryptoObject?,
+    title: CharSequence,
+    negativeButtonText: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass3BiometricAuthPrompt(
+        title,
+        negativeButtonText,
+        subtitle,
+        description,
+        confirmationRequired
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this), crypto)
+}
+
+/**
+ * Creates a [Class3BiometricAuthPrompt] with the given parameters.
+ */
+private fun buildClass3BiometricAuthPrompt(
+    title: CharSequence,
+    negativeButtonText: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): Class3BiometricAuthPrompt = Class3BiometricAuthPrompt.Builder(title, negativeButtonText)
+    .apply {
+        subtitle?.let { setSubtitle(it) }
+        description?.let { setDescription(it) }
+        setConfirmationRequired(confirmationRequired)
+    }
+    .build()
+
+/**
  * Creates a [Class3BiometricAuthPrompt] with the given parameters and starts authentication.
  */
 private fun startClass3BiometricAuthenticationInternal(
     host: AuthPromptHost,
-    crypto: BiometricPrompt.CryptoObject?,
+    crypto: CryptoObject?,
     title: CharSequence,
     negativeButtonText: CharSequence,
     subtitle: CharSequence? = null,
@@ -110,15 +237,17 @@
     executor: Executor? = null,
     callback: AuthPromptCallback
 ): AuthPrompt {
-    val prompt = Class3BiometricAuthPrompt.Builder(title, negativeButtonText).apply {
-        subtitle?.let { setSubtitle(it) }
-        description?.let { setDescription(it) }
-        setConfirmationRequired(confirmationRequired)
-    }.build()
+    val prompt = buildClass3BiometricAuthPrompt(
+        title,
+        negativeButtonText,
+        subtitle,
+        description,
+        confirmationRequired
+    )
 
     return if (executor == null) {
         prompt.startAuthentication(host, crypto, callback)
     } else {
         prompt.startAuthentication(host, crypto, executor, callback)
     }
-}
\ No newline at end of file
+}
diff --git a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricOrCredentialAuthExtensions.kt b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricOrCredentialAuthExtensions.kt
index 1376e36..ec27ec6 100755
--- a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricOrCredentialAuthExtensions.kt
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/Class3BiometricOrCredentialAuthExtensions.kt
@@ -17,12 +17,52 @@
 
 import android.os.Build
 import androidx.annotation.RequiresApi
-import androidx.biometric.BiometricPrompt
+import androidx.biometric.BiometricPrompt.AuthenticationResult
+import androidx.biometric.BiometricPrompt.CryptoObject
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
+import kotlinx.coroutines.suspendCancellableCoroutine
 import java.util.concurrent.Executor
 
 /**
+ * Shows an authentication prompt to the user.
+ *
+ * @param host A wrapper for the component that will host the prompt.
+ * @param crypto A cryptographic object to be associated with this authentication.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class3BiometricOrCredentialAuthPrompt.authenticate(
+ *     AuthPromptHost,
+ *     AuthPromptCallback
+ * )
+ *
+ * @sample androidx.biometric.samples.auth.class3BiometricOrCredentialAuth
+ */
+@RequiresApi(Build.VERSION_CODES.R)
+public suspend fun Class3BiometricOrCredentialAuthPrompt.authenticate(
+    host: AuthPromptHost,
+    crypto: CryptoObject?,
+): AuthenticationResult {
+    return suspendCancellableCoroutine { continuation ->
+        val authPrompt = startAuthentication(
+            host,
+            crypto,
+            Runnable::run,
+            CoroutineAuthPromptCallback(continuation)
+        )
+
+        continuation.invokeOnCancellation {
+            authPrompt.cancelAuthentication()
+        }
+    }
+}
+
+/**
  * Prompts the user to authenticate with a **Class 3** biometric (e.g. fingerprint, face, or iris)
  * or the screen lock credential (i.e. PIN, pattern, or password) for the device.
  *
@@ -39,7 +79,7 @@
  */
 @RequiresApi(Build.VERSION_CODES.R)
 public fun FragmentActivity.startClass3BiometricOrCredentialAuthentication(
-    crypto: BiometricPrompt.CryptoObject?,
+    crypto: CryptoObject?,
     title: CharSequence,
     subtitle: CharSequence? = null,
     description: CharSequence? = null,
@@ -68,6 +108,42 @@
  * @param subtitle An optional subtitle to be displayed on the prompt.
  * @param description An optional description to be displayed on the prompt.
  * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class3BiometricOrCredentialAuthPrompt
+ */
+@RequiresApi(Build.VERSION_CODES.R)
+public suspend fun FragmentActivity.authenticateWithClass3BiometricsOrCredentials(
+    crypto: CryptoObject?,
+    title: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass3BiometricOrCredentialAuthPrompt(
+        title,
+        subtitle,
+        description,
+        confirmationRequired
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this), crypto)
+}
+
+/**
+ * Prompts the user to authenticate with a **Class 3** biometric (e.g. fingerprint, face, or iris)
+ * or the screen lock credential (i.e. PIN, pattern, or password) for the device.
+ *
+ * @param crypto A cryptographic object to be associated with this authentication.
+ * @param title The title to be displayed on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
  * @param executor An executor for [callback] methods. If `null`, these will run on the main thread.
  * @param callback The object that will receive and process authentication events.
  * @return An [AuthPrompt] handle to the shown prompt.
@@ -76,7 +152,7 @@
  */
 @RequiresApi(Build.VERSION_CODES.R)
 public fun Fragment.startClass3BiometricOrCredentialAuthentication(
-    crypto: BiometricPrompt.CryptoObject?,
+    crypto: CryptoObject?,
     title: CharSequence,
     subtitle: CharSequence? = null,
     description: CharSequence? = null,
@@ -97,13 +173,65 @@
 }
 
 /**
+ * Prompts the user to authenticate with a **Class 3** biometric (e.g. fingerprint, face, or iris)
+ * or the screen lock credential (i.e. PIN, pattern, or password) for the device.
+ *
+ * @param crypto A cryptographic object to be associated with this authentication.
+ * @param title The title to be displayed on the prompt.
+ * @param subtitle An optional subtitle to be displayed on the prompt.
+ * @param description An optional description to be displayed on the prompt.
+ * @param confirmationRequired Whether user confirmation should be required for passive biometrics.
+ *
+ * @return [AuthenticationResult] for a successful authentication.
+ *
+ * @throws AuthPromptErrorException  when an unrecoverable error has been encountered and
+ * authentication has stopped.
+ * @throws AuthPromptFailureException when an authentication attempt by the user has been rejected.
+ *
+ * @see Class3BiometricOrCredentialAuthPrompt
+ */
+@RequiresApi(Build.VERSION_CODES.R)
+public suspend fun Fragment.authenticateWithClass3BiometricsOrCredentials(
+    crypto: CryptoObject?,
+    title: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): AuthenticationResult {
+    val authPrompt = buildClass3BiometricOrCredentialAuthPrompt(
+        title,
+        subtitle,
+        description,
+        confirmationRequired,
+    )
+
+    return authPrompt.authenticate(AuthPromptHost(this), crypto)
+}
+
+/**
+ * Creates a [Class3BiometricOrCredentialAuthPrompt] with the given parameters.
+ */
+private fun buildClass3BiometricOrCredentialAuthPrompt(
+    title: CharSequence,
+    subtitle: CharSequence? = null,
+    description: CharSequence? = null,
+    confirmationRequired: Boolean = true,
+): Class3BiometricOrCredentialAuthPrompt = Class3BiometricOrCredentialAuthPrompt.Builder(title)
+    .apply {
+        subtitle?.let { setSubtitle(it) }
+        description?.let { setDescription(it) }
+        setConfirmationRequired(confirmationRequired)
+    }
+    .build()
+
+/**
  * Creates a [Class3BiometricOrCredentialAuthPrompt] with the given parameters and starts
  * authentication.
  */
 @RequiresApi(Build.VERSION_CODES.R)
 private fun startClass3BiometricOrCredentialAuthenticationInternal(
     host: AuthPromptHost,
-    crypto: BiometricPrompt.CryptoObject?,
+    crypto: CryptoObject?,
     title: CharSequence,
     subtitle: CharSequence? = null,
     description: CharSequence? = null,
@@ -111,15 +239,16 @@
     executor: Executor? = null,
     callback: AuthPromptCallback
 ): AuthPrompt {
-    val prompt = Class3BiometricOrCredentialAuthPrompt.Builder(title).apply {
-        subtitle?.let { setSubtitle(it) }
-        description?.let { setDescription(it) }
-        setConfirmationRequired(confirmationRequired)
-    }.build()
+    val prompt = buildClass3BiometricOrCredentialAuthPrompt(
+        title,
+        subtitle,
+        description,
+        confirmationRequired
+    )
 
     return if (executor == null) {
         prompt.startAuthentication(host, crypto, callback)
     } else {
         prompt.startAuthentication(host, crypto, executor, callback)
     }
-}
\ No newline at end of file
+}
diff --git a/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/CoroutineAuthPromptCallback.kt b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/CoroutineAuthPromptCallback.kt
new file mode 100644
index 0000000..fb6de45
--- /dev/null
+++ b/biometric/biometric-ktx/src/main/java/androidx/biometric/auth/CoroutineAuthPromptCallback.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.biometric.auth
+
+import androidx.biometric.BiometricPrompt.AuthenticationResult
+import androidx.fragment.app.FragmentActivity
+import kotlinx.coroutines.CancellableContinuation
+import kotlin.coroutines.resumeWithException
+
+/**
+ * Implementation of [AuthPromptCallback] used to transform callback results for coroutine APIs.
+ */
+internal class CoroutineAuthPromptCallback(
+    private val continuation: CancellableContinuation<AuthenticationResult>
+) : AuthPromptCallback() {
+    override fun onAuthenticationError(
+        activity: FragmentActivity?,
+        errorCode: Int,
+        errString: CharSequence
+    ) {
+        continuation.resumeWithException(AuthPromptErrorException(errorCode, errString))
+    }
+
+    override fun onAuthenticationSucceeded(
+        activity: FragmentActivity?,
+        result: AuthenticationResult
+    ) {
+        continuation.resumeWith(Result.success(result))
+    }
+
+    override fun onAuthenticationFailed(activity: FragmentActivity?) {
+        continuation.resumeWithException(AuthPromptFailureException())
+    }
+}
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java
index 4f83a98..c126640 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java
@@ -371,14 +371,12 @@
             return BIOMETRIC_ERROR_NO_HARDWARE;
         }
 
-        // No authenticators are enrolled if the device is not secured.
-        if (!mInjector.isDeviceSecuredWithCredential()) {
-            return BIOMETRIC_ERROR_NONE_ENROLLED;
-        }
-
-        // Credential authentication is always possible if the device is secured.
+        // Credential authentication is always possible if the device is secured. Conversely, no
+        // form of authentication is possible if the device is not secured.
         if (AuthenticatorUtils.isDeviceCredentialAllowed(authenticators)) {
-            return BIOMETRIC_SUCCESS;
+            return mInjector.isDeviceSecuredWithCredential()
+                    ? BIOMETRIC_SUCCESS
+                    : BIOMETRIC_ERROR_NONE_ENROLLED;
         }
 
         // The class of some non-fingerprint biometrics can be checked on API 29.
@@ -393,7 +391,7 @@
             // Having fingerprint hardware is a prerequisite, since BiometricPrompt internally
             // calls FingerprintManager#getErrorString() on API 28 (b/151443237).
             return mInjector.isFingerprintHardwarePresent()
-                    ? canAuthenticateWithFingerprintOrUnknown()
+                    ? canAuthenticateWithFingerprintOrUnknownBiometric()
                     : BIOMETRIC_ERROR_NO_HARDWARE;
         }
 
@@ -443,7 +441,7 @@
         }
 
         // If all else fails, check if fingerprint authentication is available.
-        return canAuthenticateWithFingerprintOrUnknown();
+        return canAuthenticateWithFingerprintOrUnknownBiometric();
     }
 
     /**
@@ -465,14 +463,23 @@
     }
 
     /**
-     * Checks if the user can authenticate with fingerprint, falling back to
-     * {@link #BIOMETRIC_STATUS_UNKNOWN} for any error condition.
+     * Checks if the user can authenticate with fingerprint or with a biometric sensor for which
+     * there is no platform method to check availability.
      *
-     * @return {@link #BIOMETRIC_SUCCESS} if the user can authenticate with fingerprint, or
-     * {@link #BIOMETRIC_STATUS_UNKNOWN} otherwise.
+     * @return {@link #BIOMETRIC_SUCCESS} if the user can authenticate with fingerprint. Otherwise,
+     * returns an error code indicating why the user can't authenticate, or
+     * {@link #BIOMETRIC_STATUS_UNKNOWN} if it is unknown whether the user can authenticate.
      */
     @AuthenticationStatus
-    private int canAuthenticateWithFingerprintOrUnknown() {
+    private int canAuthenticateWithFingerprintOrUnknownBiometric() {
+        // If the device is not secured, authentication is definitely not possible. Use
+        // FingerprintManager to distinguish between the "no hardware" and "none enrolled" cases.
+        if (!mInjector.isDeviceSecuredWithCredential()) {
+            return canAuthenticateWithFingerprint();
+        }
+
+        // Check for definite availability of fingerprint. Otherwise, return "unknown" to allow for
+        // non-fingerprint biometrics (e.g. iris) that may be available via BiometricPrompt.
         return canAuthenticateWithFingerprint() == BIOMETRIC_SUCCESS
                 ? BIOMETRIC_SUCCESS
                 : BIOMETRIC_STATUS_UNKNOWN;
diff --git a/biometric/biometric/src/test/java/androidx/biometric/BiometricManagerTest.java b/biometric/biometric/src/test/java/androidx/biometric/BiometricManagerTest.java
index abbd6f0..d359008 100644
--- a/biometric/biometric/src/test/java/androidx/biometric/BiometricManagerTest.java
+++ b/biometric/biometric/src/test/java/androidx/biometric/BiometricManagerTest.java
@@ -240,39 +240,78 @@
 
     @Test
     @Config(minSdk = Build.VERSION_CODES.Q, maxSdk = Build.VERSION_CODES.Q)
-    public void testCanAuthenticate_ReturnsError_WhenDeviceNotSecured_OnApi29() {
+    public void testCanAuthenticate_ReturnsError_WhenUnsecured_BiometricOnly_OnApi29() {
         final android.hardware.biometrics.BiometricManager frameworkBiometricManager =
                 mock(android.hardware.biometrics.BiometricManager.class);
-        when(frameworkBiometricManager.canAuthenticate()).thenReturn(BIOMETRIC_SUCCESS);
-        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
-        when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(true);
+        when(frameworkBiometricManager.canAuthenticate()).thenReturn(BIOMETRIC_ERROR_NO_HARDWARE);
+        when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+        when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false);
 
         final BiometricManager.Injector injector = new TestInjector.Builder()
                 .setBiometricManager(frameworkBiometricManager)
                 .setDeviceSecurable(true)
-                .setFingerprintHardwarePresent(true)
+                .setFingerprintHardwarePresent(false)
                 .build();
 
         final BiometricManager biometricManager = new BiometricManager(injector);
         final int authenticators = Authenticators.BIOMETRIC_WEAK;
         assertThat(biometricManager.canAuthenticate(authenticators))
+                .isEqualTo(BIOMETRIC_ERROR_NO_HARDWARE);
+    }
+
+    @Test
+    @Config(maxSdk = Build.VERSION_CODES.P)
+    public void testCanAuthenticate_ReturnsError_WhenUnsecured_BiometricOnly_OnApi28AndBelow() {
+        when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+        when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false);
+
+        final BiometricManager.Injector injector = new TestInjector.Builder()
+                .setFingerprintManager(mFingerprintManager)
+                .setDeviceSecurable(true)
+                .setFingerprintHardwarePresent(false)
+                .build();
+
+        final BiometricManager biometricManager = new BiometricManager(injector);
+        final int authenticators = Authenticators.BIOMETRIC_WEAK;
+        assertThat(biometricManager.canAuthenticate(authenticators))
+                .isEqualTo(BIOMETRIC_ERROR_NO_HARDWARE);
+    }
+
+    @Test
+    @Config(minSdk = Build.VERSION_CODES.Q, maxSdk = Build.VERSION_CODES.Q)
+    public void testCanAuthenticate_ReturnsError_WhenUnsecured_CredentialAllowed_OnApi29() {
+        final android.hardware.biometrics.BiometricManager frameworkBiometricManager =
+                mock(android.hardware.biometrics.BiometricManager.class);
+        when(frameworkBiometricManager.canAuthenticate()).thenReturn(BIOMETRIC_ERROR_NO_HARDWARE);
+        when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+        when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false);
+
+        final BiometricManager.Injector injector = new TestInjector.Builder()
+                .setBiometricManager(frameworkBiometricManager)
+                .setDeviceSecurable(true)
+                .setFingerprintHardwarePresent(false)
+                .build();
+
+        final BiometricManager biometricManager = new BiometricManager(injector);
+        final int authenticators = Authenticators.BIOMETRIC_WEAK | Authenticators.DEVICE_CREDENTIAL;
+        assertThat(biometricManager.canAuthenticate(authenticators))
                 .isEqualTo(BIOMETRIC_ERROR_NONE_ENROLLED);
     }
 
     @Test
     @Config(maxSdk = Build.VERSION_CODES.P)
-    public void testCanAuthenticate_ReturnsError_WhenDeviceNotSecured_OnApi28AndBelow() {
-        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
-        when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(true);
+    public void testCanAuthenticate_ReturnsError_WhenUnsecured_CredentialAllowed_OnApi28AndBelow() {
+        when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+        when(mFingerprintManager.hasEnrolledFingerprints()).thenReturn(false);
 
         final BiometricManager.Injector injector = new TestInjector.Builder()
                 .setFingerprintManager(mFingerprintManager)
                 .setDeviceSecurable(true)
-                .setFingerprintHardwarePresent(true)
+                .setFingerprintHardwarePresent(false)
                 .build();
 
         final BiometricManager biometricManager = new BiometricManager(injector);
-        final int authenticators = Authenticators.BIOMETRIC_WEAK;
+        final int authenticators = Authenticators.BIOMETRIC_WEAK | Authenticators.DEVICE_CREDENTIAL;
         assertThat(biometricManager.canAuthenticate(authenticators))
                 .isEqualTo(BIOMETRIC_ERROR_NONE_ENROLLED);
     }
diff --git a/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/AuthPromptTestActivity.kt b/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/AuthPromptTestActivity.kt
index 896f04e8..0e92e2a 100755
--- a/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/AuthPromptTestActivity.kt
+++ b/biometric/integration-tests/testapp/src/main/java/androidx/biometric/integration/testapp/AuthPromptTestActivity.kt
@@ -26,7 +26,7 @@
 import androidx.biometric.auth.AuthPromptCallback
 import androidx.biometric.auth.startClass2BiometricAuthentication
 import androidx.biometric.auth.startClass2BiometricOrCredentialAuthentication
-import androidx.biometric.auth.startClass3BiometricAuthentication
+import androidx.biometric.auth.authenticateWithClass3Biometrics
 import androidx.biometric.auth.startClass3BiometricOrCredentialAuthentication
 import androidx.biometric.auth.startCredentialAuthentication
 import androidx.biometric.integration.testapp.R.string.biometric_prompt_description
@@ -191,7 +191,7 @@
                 )
 
             R.id.class3_biometric_button ->
-                startClass3BiometricAuthentication(
+                authenticateWithClass3Biometrics(
                     crypto = createCryptoOrNull(),
                     title = title,
                     subtitle = subtitle,
diff --git a/biometric/settings.gradle b/biometric/settings.gradle
index 697db78..7a96db8 100644
--- a/biometric/settings.gradle
+++ b/biometric/settings.gradle
@@ -20,6 +20,7 @@
 setupPlayground(this, "..")
 selectProjectsFromAndroidX({ name ->
     if (name.startsWith(":biometric")) return true
+    if (name == ":annotation:annotation-sampled") return true
     return false
 })
 
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
index 629c6f6..1663e7b 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
@@ -129,6 +129,24 @@
     }
 
     @Test
+    public void exceedMaxImagesWithoutClosing_doNotCrash() throws InterruptedException {
+        // Arrange.
+        int queueDepth = 3;
+        Semaphore semaphore = new Semaphore(0);
+        ImageAnalysis useCase = new ImageAnalysis.Builder()
+                .setBackpressureStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER)
+                .setImageQueueDepth(queueDepth)
+                .build();
+        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler),
+                image -> semaphore.release());
+        // Act.
+        mCamera = CameraUtil.createCameraAndAttachUseCase(mContext,
+                CameraSelector.DEFAULT_FRONT_CAMERA, useCase);
+        // Assert: waiting for images does not crash.
+        assertThat(semaphore.tryAcquire(queueDepth + 1, /*timeout=*/1, TimeUnit.SECONDS)).isFalse();
+    }
+
+    @Test
     public void canSupportGuaranteedSizeFront()
             throws InterruptedException, CameraInfoUnavailableException {
         // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
diff --git a/camera/camera-core/lint-baseline.xml b/camera/camera-core/lint-baseline.xml
index 65899e9..1df7dc7 100644
--- a/camera/camera-core/lint-baseline.xml
+++ b/camera/camera-core/lint-baseline.xml
@@ -334,50 +334,6 @@
     <issue
         id="BanSynchronizedMethods"
         message="Use of synchronized methods is not recommended"
-        errorLine1="    @Override"
-        errorLine2="    ^">
-        <location
-            file="src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java"
-            line="73"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="BanSynchronizedMethods"
-        message="Use of synchronized methods is not recommended"
-        errorLine1="    @Override"
-        errorLine2="    ^">
-        <location
-            file="src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java"
-            line="82"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="BanSynchronizedMethods"
-        message="Use of synchronized methods is not recommended"
-        errorLine1="    /**"
-        errorLine2="    ^">
-        <location
-            file="src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java"
-            line="91"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="BanSynchronizedMethods"
-        message="Use of synchronized methods is not recommended"
-        errorLine1="    /**"
-        errorLine2="    ^">
-        <location
-            file="src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java"
-            line="102"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="BanSynchronizedMethods"
-        message="Use of synchronized methods is not recommended"
         errorLine1="        @Override"
         errorLine2="        ^">
         <location
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
index 9554cff..97735cb 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysis.java
@@ -215,7 +215,6 @@
 
         tryUpdateRelativeRotation();
 
-        mImageAnalysisAbstractAnalyzer.open();
         imageReaderProxy.setOnImageAvailableListener(mImageAnalysisAbstractAnalyzer,
                 backgroundExecutor);
 
@@ -233,7 +232,8 @@
 
         sessionConfigBuilder.addErrorListener((sessionConfig, error) -> {
             clearPipeline();
-
+            // Clear cache so app won't get a outdated image.
+            mImageAnalysisAbstractAnalyzer.clearCache();
             // Ensure the attached camera has not changed before resetting.
             // TODO(b/143915543): Ensure this never gets called by a camera that is not attached
             //  to this use case so we don't need to do this check.
@@ -256,8 +256,6 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     void clearPipeline() {
         Threads.checkMainThread();
-        mImageAnalysisAbstractAnalyzer.close();
-
         if (mDeferrableSurface != null) {
             mDeferrableSurface.close();
             mDeferrableSurface = null;
@@ -272,7 +270,6 @@
     public void clearAnalyzer() {
         synchronized (mAnalysisLock) {
             mImageAnalysisAbstractAnalyzer.setAnalyzer(null, null);
-            mImageAnalysisAbstractAnalyzer.close();
             if (mSubscribedAnalyzer != null) {
                 notifyInactive();
             }
@@ -363,7 +360,6 @@
      */
     public void setAnalyzer(@NonNull Executor executor, @NonNull Analyzer analyzer) {
         synchronized (mAnalysisLock) {
-            mImageAnalysisAbstractAnalyzer.open();
             mImageAnalysisAbstractAnalyzer.setAnalyzer(executor, image -> {
                 if (getViewPortCropRect() != null) {
                     image.setCropRect(getViewPortCropRect());
@@ -430,6 +426,7 @@
     @Override
     public void onDetached() {
         clearPipeline();
+        mImageAnalysisAbstractAnalyzer.detach();
     }
 
     /**
@@ -460,14 +457,7 @@
     @Override
     @RestrictTo(Scope.LIBRARY_GROUP)
     public void onAttached() {
-        synchronized (mAnalysisLock) {
-            // The use case should be reused so that mSubscribedAnalyzer is not null but
-            // mImageAnalysisAbstractAnalyzer is closed. Re-open mImageAnalysisAbstractAnalyzer
-            // after the use case is attached to make it work again.
-            if (mSubscribedAnalyzer != null && mImageAnalysisAbstractAnalyzer.isClosed()) {
-                mImageAnalysisAbstractAnalyzer.open();
-            }
-        }
+        mImageAnalysisAbstractAnalyzer.attach();
     }
 
     /**
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java
index 01f33b4..19777ad 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisAbstractAnalyzer.java
@@ -17,6 +17,7 @@
 package androidx.camera.core;
 
 import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.camera.core.impl.ImageReaderProxy;
 import androidx.camera.core.impl.utils.futures.Futures;
@@ -26,7 +27,6 @@
 import com.google.common.util.concurrent.ListenableFuture;
 
 import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Abstract Analyzer that wraps around {@link ImageAnalysis.Analyzer} and implements
@@ -37,6 +37,8 @@
  */
 abstract class ImageAnalysisAbstractAnalyzer implements ImageReaderProxy.OnImageAvailableListener {
 
+    private static final String TAG = "ImageAnalysisAnalyzer";
+
     // Member variables from ImageAnalysis.
     @GuardedBy("mAnalyzerLock")
     private ImageAnalysis.Analyzer mSubscribedAnalyzer;
@@ -44,16 +46,48 @@
     @GuardedBy("mAnalyzerLock")
     private Executor mUserExecutor;
 
+    // Lock that synchronizes the access to mSubscribedAnalyzer/mUserExecutor to prevent mismatch.
     private final Object mAnalyzerLock = new Object();
 
-    // Flag that reflects the state of ImageAnalysis.
-    private AtomicBoolean mIsClosed;
+    // Flag that reflects the attaching state of the holding ImageAnalysis object.
+    protected boolean mIsAttached = true;
 
-    ImageAnalysisAbstractAnalyzer() {
-        mIsClosed = new AtomicBoolean(false);
+    @Override
+    public void onImageAvailable(@NonNull ImageReaderProxy imageReaderProxy) {
+        try {
+            ImageProxy imageProxy = acquireImage(imageReaderProxy);
+            if (imageProxy != null) {
+                onValidImageAvailable(imageProxy);
+            }
+        } catch (IllegalStateException e) {
+            // This happens if image is not closed in STRATEGY_BLOCK_PRODUCER mode. Catch the
+            // exception and fail with an error log.
+            // TODO(b/175851631): it may also happen when STRATEGY_KEEP_ONLY_LATEST not closing
+            //  the cached image properly. We are unclear why it happens but catching the
+            //  exception should improve the situation by not crashing.
+            Logger.e(TAG, "Failed to acquire image.", e);
+        }
     }
 
     /**
+     * Implemented by children to acquireImage via {@link ImageReaderProxy#acquireLatestImage()} or
+     * {@link ImageReaderProxy#acquireNextImage()}.
+     */
+    @Nullable
+    abstract ImageProxy acquireImage(@NonNull ImageReaderProxy imageReaderProxy);
+
+    /**
+     * Called when a new valid {@link ImageProxy} becomes available via
+     * {@link ImageReaderProxy.OnImageAvailableListener}.
+     */
+    abstract void onValidImageAvailable(@NonNull ImageProxy imageProxy);
+
+    /**
+     * Called by {@link ImageAnalysis} to release cached images.
+     */
+    abstract void clearCache();
+
+    /**
      * Analyzes a {@link ImageProxy} using the wrapped {@link ImageAnalysis.Analyzer}.
      *
      * <p> The analysis will run on the executor provided by {@link #setAnalyzer(Executor,
@@ -76,9 +110,9 @@
         if (analyzer != null && executor != null) {
             // When the analyzer exists and ImageAnalysis is active.
             future = CallbackToFutureAdapter.getFuture(
-                    completer ->  {
+                    completer -> {
                         executor.execute(() -> {
-                            if (!isClosed()) {
+                            if (mIsAttached) {
                                 ImageInfo imageInfo = ImmutableImageInfo.create(
                                         imageProxy.getImageInfo().getTagBundle(),
                                         imageProxy.getImageInfo().getTimestamp(),
@@ -87,15 +121,15 @@
                                 analyzer.analyze(new SettableImageProxy(imageProxy, imageInfo));
                                 completer.set(null);
                             } else {
-                                completer.setException(new OperationCanceledException("Closed "
-                                        + "before analysis"));
+                                completer.setException(new OperationCanceledException(
+                                        "ImageAnalysis is detached"));
                             }
                         });
-                    return "analyzeImage";
+                        return "analyzeImage";
                     });
         } else {
-            future = Futures.immediateFailedFuture(new OperationCanceledException("No analyzer "
-                    + "or executor currently set."));
+            future = Futures.immediateFailedFuture(new OperationCanceledException(
+                    "No analyzer or executor currently set."));
         }
 
         return future;
@@ -108,6 +142,9 @@
     void setAnalyzer(@Nullable Executor userExecutor,
             @Nullable ImageAnalysis.Analyzer subscribedAnalyzer) {
         synchronized (mAnalyzerLock) {
+            if (subscribedAnalyzer == null) {
+                clearCache();
+            }
             mSubscribedAnalyzer = subscribedAnalyzer;
             mUserExecutor = userExecutor;
         }
@@ -116,19 +153,15 @@
     /**
      * Initialize the callback.
      */
-    void open() {
-        mIsClosed.set(false);
+    void attach() {
+        mIsAttached = true;
     }
 
     /**
      * Closes the callback so that it will stop posting to analyzer.
      */
-    void close() {
-        mIsClosed.set(true);
+    void detach() {
+        mIsAttached = false;
+        clearCache();
     }
-
-    boolean isClosed() {
-        return mIsClosed.get();
-    }
-
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java
index 4a43004..df579f5 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisBlockingAnalyzer.java
@@ -17,6 +17,7 @@
 package androidx.camera.core;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.camera.core.impl.ImageReaderProxy;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.FutureCallback;
@@ -31,14 +32,16 @@
  */
 final class ImageAnalysisBlockingAnalyzer extends ImageAnalysisAbstractAnalyzer {
 
+    @Nullable
     @Override
-    public void onImageAvailable(@NonNull ImageReaderProxy imageReaderProxy) {
-        ImageProxy image = imageReaderProxy.acquireNextImage();
-        if (image == null) {
-            return;
-        }
+    ImageProxy acquireImage(@NonNull ImageReaderProxy imageReaderProxy) {
+        // Use acquireNextImage() so it never drops older images.
+        return imageReaderProxy.acquireNextImage();
+    }
 
-        ListenableFuture<Void> analyzeFuture = analyzeImage(image);
+    @Override
+    void onValidImageAvailable(@NonNull ImageProxy imageProxy) {
+        ListenableFuture<Void> analyzeFuture = analyzeImage(imageProxy);
 
         // Callback to close the image only after analysis complete regardless of success
         Futures.addCallback(analyzeFuture, new FutureCallback<Void>() {
@@ -49,8 +52,13 @@
 
             @Override
             public void onFailure(Throwable t) {
-                image.close();
+                imageProxy.close();
             }
         }, CameraXExecutors.directExecutor());
     }
+
+    @Override
+    void clearCache() {
+        // no-op. The blocking analyzer does not cache images.
+    }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java
index a9a3151..792b3b8 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzer.java
@@ -18,17 +18,15 @@
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.impl.ImageReaderProxy;
 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 com.google.common.util.concurrent.ListenableFuture;
-
 import java.lang.ref.WeakReference;
 import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * OnImageAvailableListener with non-blocking behavior. Analyzes images in a non-blocking way by
@@ -38,65 +36,33 @@
  */
 final class ImageAnalysisNonBlockingAnalyzer extends ImageAnalysisAbstractAnalyzer {
 
-    private static final String TAG = "NonBlockingCallback";
-
     // The executor for managing cached image.
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     final Executor mBackgroundExecutor;
 
+    private final Object mLock = new Object();
+
     // The cached image when analyzer is busy. Image removed from cache must be closed by 1) closing
     // it directly or 2) re-posting it to close it eventually.
-    @GuardedBy("this")
-    private ImageProxy mCachedImage;
+    @GuardedBy("mLock")
+    @Nullable
+    @VisibleForTesting
+    ImageProxy mCachedImage;
 
-    // Timestamp of the last image posted to user callback thread.
-    private final AtomicLong mPostedImageTimestamp;
-
-    private final AtomicReference<CacheAnalyzingImageProxy> mPostedImage;
+    // The latest unclosed image sent to the app.
+    @GuardedBy("mLock")
+    @Nullable
+    private CacheAnalyzingImageProxy mPostedImage;
 
     ImageAnalysisNonBlockingAnalyzer(Executor executor) {
         mBackgroundExecutor = executor;
-        mPostedImage = new AtomicReference<>();
-        mPostedImageTimestamp = new AtomicLong();
-        open();
     }
 
+    @Nullable
     @Override
-    public void onImageAvailable(@NonNull ImageReaderProxy imageReaderProxy) {
-        ImageProxy imageProxy = imageReaderProxy.acquireLatestImage();
-        if (imageProxy == null) {
-            return;
-        }
-        analyze(imageProxy);
-    }
-
-    @Override
-    synchronized void open() {
-        super.open();
-        if (mCachedImage != null) {
-            mCachedImage.close();
-            mCachedImage = null;
-        }
-    }
-
-    @Override
-    synchronized void close() {
-        super.close();
-        if (mCachedImage != null) {
-            mCachedImage.close();
-            mCachedImage = null;
-        }
-    }
-
-    /**
-     * Removes cached image from cache and analyze it.
-     */
-    synchronized void analyzeCachedImage() {
-        if (mCachedImage != null) {
-            ImageProxy cachedImage = mCachedImage;
-            mCachedImage = null;
-            analyze(cachedImage);
-        }
+    ImageProxy acquireImage(@NonNull ImageReaderProxy imageReaderProxy) {
+        // Use acquireLatestImage() so older images should be released.
+        return imageReaderProxy.acquireLatestImage();
     }
 
     /**
@@ -105,60 +71,82 @@
      *
      * @param imageProxy the incoming image frame.
      */
-    private synchronized void analyze(@NonNull ImageProxy imageProxy) {
-        if (isClosed()) {
-            imageProxy.close();
-            return;
-        }
+    @Override
+    void onValidImageAvailable(@NonNull ImageProxy imageProxy) {
+        synchronized (mLock) {
+            if (!mIsAttached) {
+                imageProxy.close();
+                return;
+            }
+            if (mPostedImage != null) {
+                // There is unclosed image held by the app. The incoming image has to wait.
 
-        CacheAnalyzingImageProxy postedImage = mPostedImage.get();
-        if (postedImage != null
-                && imageProxy.getImageInfo().getTimestamp() <= mPostedImageTimestamp.get()) {
-            // Discard image that is in wrong order. Reposted cached image can be in this state.
-            imageProxy.close();
-            return;
-        }
+                if (imageProxy.getImageInfo().getTimestamp()
+                        <= mPostedImage.getImageInfo().getTimestamp()) {
+                    // Discard the incoming image that is in the wrong order. Cached image can be
+                    // in this state.
+                    imageProxy.close();
+                } else {
+                    // Otherwise cache the incoming image and repost it later.
+                    if (mCachedImage != null) {
+                        mCachedImage.close();
+                    }
+                    mCachedImage = imageProxy;
+                }
+                return;
+            }
 
-        if (postedImage != null && !postedImage.isClosed()) {
-            // If the posted image hasn't been closed, cache the new image.
+            // Post the incoming image to app.
+            final CacheAnalyzingImageProxy newPostedImage = new CacheAnalyzingImageProxy(imageProxy,
+                    this);
+            mPostedImage = newPostedImage;
+            Futures.addCallback(analyzeImage(newPostedImage), new FutureCallback<Void>() {
+                @Override
+                public void onSuccess(Void result) {
+                    // No-op. If the post is successful, app should close it.
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    // Close the image if we didn't post it to user.
+                    newPostedImage.close();
+                }
+            }, CameraXExecutors.directExecutor());
+        }
+    }
+
+    @Override
+    void clearCache() {
+        synchronized (mLock) {
             if (mCachedImage != null) {
                 mCachedImage.close();
+                mCachedImage = null;
             }
-            mCachedImage = imageProxy;
-            return;
         }
-
-        final CacheAnalyzingImageProxy newPostedImage = new CacheAnalyzingImageProxy(imageProxy,
-                this);
-        mPostedImage.set(newPostedImage);
-        mPostedImageTimestamp.set(newPostedImage.getImageInfo().getTimestamp());
-
-        ListenableFuture<Void> analyzeFuture = analyzeImage(newPostedImage);
-
-        // Callback to close the image only after analysis complete regardless of success
-        Futures.addCallback(analyzeFuture, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(Void result) {
-                // No-op. Keep dropping the images until user closes the current one.
-            }
-
-            @Override
-            public void onFailure(Throwable t) {
-                // Close the image if we didn't post it to user.
-                newPostedImage.close();
-            }
-        }, CameraXExecutors.directExecutor());
     }
 
     /**
-     * An {@link ImageProxy} which will trigger analysis of the cached ImageProxy if it exists.
+     * Removes cached image from cache and analyze it.
+     */
+    void analyzeCachedImage() {
+        synchronized (mLock) {
+            mPostedImage = null;
+            if (mCachedImage != null) {
+                ImageProxy cachedImage = mCachedImage;
+                mCachedImage = null;
+                onValidImageAvailable(cachedImage);
+            }
+        }
+    }
+
+    /**
+     * An {@link ImageProxy} that analyze cached image on close.
      */
     static class CacheAnalyzingImageProxy extends ForwardingImageProxy {
 
-        // So that if the user holds onto the ImageProxy instance the analyzer can still be GC'ed
-        WeakReference<ImageAnalysisNonBlockingAnalyzer> mNonBlockingAnalyzerWeakReference;
-
-        private boolean mClosed = false;
+        // WeakReference so that if the app holds onto the ImageProxy instance the analyzer can
+        // still be GCed.
+        final WeakReference<ImageAnalysisNonBlockingAnalyzer> mNonBlockingAnalyzerWeakReference;
 
         /**
          * Creates a new instance which wraps the given image.
@@ -172,16 +160,11 @@
             mNonBlockingAnalyzerWeakReference = new WeakReference<>(nonBlockingAnalyzer);
 
             addOnImageCloseListener((imageProxy) -> {
-                mClosed = true;
                 ImageAnalysisNonBlockingAnalyzer analyzer = mNonBlockingAnalyzerWeakReference.get();
                 if (analyzer != null) {
                     analyzer.mBackgroundExecutor.execute(analyzer::analyzeCachedImage);
                 }
             });
         }
-
-        boolean isClosed() {
-            return mClosed;
-        }
     }
 }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java
index 7f647f5..3f48a51 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisNonBlockingAnalyzerTest.java
@@ -26,7 +26,6 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 
@@ -46,6 +45,9 @@
 
 import java.util.concurrent.atomic.AtomicInteger;
 
+/**
+ * Unit tests for {@link ImageAnalysisNonBlockingAnalyzer}
+ */
 @RunWith(RobolectricTestRunner.class)
 @DoNotInstrument
 @Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
@@ -78,43 +80,36 @@
         mImageAnalysisNonBlockingAnalyzer.setAnalyzer(CameraXExecutors.mainThreadExecutor(),
                 mAnalyzer);
         mImageAnalysisNonBlockingAnalyzer.setRelativeRotation(ROTATION.get());
+        mImageAnalysisNonBlockingAnalyzer.attach();
     }
 
     @Test
-    public void imageClosedAfterAnalyzerClosed() {
-        mImageAnalysisNonBlockingAnalyzer.close();
-
+    public void imageClosedAfterAnalyzerDetached() {
+        // Arrange.
+        mImageAnalysisNonBlockingAnalyzer.detach();
+        // Act.
         mImageAnalysisNonBlockingAnalyzer.onImageAvailable(mImageReaderProxy);
-
+        shadowOf(getMainLooper()).idle();
+        // Assert.
         verify(mImageProxy, times(1)).close();
     }
 
     @Test
-    public void analysisNotRunAfterAnalyzerClosed() {
-        mImageAnalysisNonBlockingAnalyzer.close();
-
+    public void imageNotClosedWhenAnalyzerAttached() {
+        // Act.
         mImageAnalysisNonBlockingAnalyzer.onImageAvailable(mImageReaderProxy);
-
-        verifyZeroInteractions(mAnalyzer);
-    }
-
-    @Test
-    public void imageNotClosedWhenAnalyzerOpen() {
-        mImageAnalysisNonBlockingAnalyzer.open();
-
-        mImageAnalysisNonBlockingAnalyzer.onImageAvailable(mImageReaderProxy);
-
+        shadowOf(getMainLooper()).idle();
+        // Assert.
         verify(mImageProxy, never()).close();
     }
 
     @Test
-    public void analysisRunWhenAnalyzerOpen() {
-        mImageAnalysisNonBlockingAnalyzer.open();
-
+    public void analysisRunWhenAnalyzerAttached() {
+        // Act.
         mImageAnalysisNonBlockingAnalyzer.onImageAvailable(mImageReaderProxy);
-
         shadowOf(getMainLooper()).idle();
 
+        // Assert.
         ArgumentCaptor<ImageProxy> imageProxyArgumentCaptor =
                 ArgumentCaptor.forClass(ImageProxy.class);
         verify(mAnalyzer, times(1)).analyze(
@@ -129,15 +124,33 @@
     }
 
     @Test
-    public void imageClosedWhenAnalyzerNull() {
-        mImageAnalysisNonBlockingAnalyzer.setAnalyzer(CameraXExecutors.mainThreadExecutor(), null);
-        mImageAnalysisNonBlockingAnalyzer.open();
+    public void setAnalyzerNull_incomingImageClosed() {
+        // Arrange.
+        mImageAnalysisNonBlockingAnalyzer.setAnalyzer(null, null);
+        // Act.
         mImageAnalysisNonBlockingAnalyzer.onImageAvailable(mImageReaderProxy);
+        shadowOf(getMainLooper()).idle();
+        // Assert.
+        verify(mImageProxy).close();
+    }
 
-        final ArgumentCaptor<ImageAnalysisNonBlockingAnalyzer.CacheAnalyzingImageProxy>
-                imageProxyToAnalyze = ArgumentCaptor.forClass(
-                ImageAnalysisNonBlockingAnalyzer.CacheAnalyzingImageProxy.class);
-        verify(mImageAnalysisNonBlockingAnalyzer).analyzeImage(imageProxyToAnalyze.capture());
-        assertThat(imageProxyToAnalyze.getValue().isClosed()).isTrue();
+    @Test
+    public void closeAnalyzer_cachedImageBecomesNull() {
+        // Arrange.
+        mImageAnalysisNonBlockingAnalyzer.mCachedImage = mImageProxy;
+        // Act.
+        mImageAnalysisNonBlockingAnalyzer.setAnalyzer(null, null);
+        // Assert.
+        assertThat(mImageAnalysisNonBlockingAnalyzer.mCachedImage).isNull();
+    }
+
+    @Test
+    public void detachAnalyzer_cachedImageBecomesNull() {
+        // Arrange.
+        mImageAnalysisNonBlockingAnalyzer.mCachedImage = mImageProxy;
+        // Act.
+        mImageAnalysisNonBlockingAnalyzer.detach();
+        // Assert.
+        assertThat(mImageAnalysisNonBlockingAnalyzer.mCachedImage).isNull();
     }
 }
diff --git a/car/app/app-aaos/api/current.txt b/car/app/app-aaos/api/current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/car/app/app-aaos/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/car/app/app-aaos/api/public_plus_experimental_current.txt b/car/app/app-aaos/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/car/app/app-aaos/api/public_plus_experimental_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/car/app/app-aaos/api/res-current.txt b/car/app/app-aaos/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/car/app/app-aaos/api/res-current.txt
diff --git a/car/app/app-aaos/api/restricted_current.txt b/car/app/app-aaos/api/restricted_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/car/app/app-aaos/api/restricted_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/car/app/app-aaos/build.gradle b/car/app/app-aaos/build.gradle
new file mode 100644
index 0000000..87a2082
--- /dev/null
+++ b/car/app/app-aaos/build.gradle
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import androidx.build.LibraryGroups
+import androidx.build.LibraryType
+import androidx.build.Publish
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+}
+
+dependencies {
+    // Add dependencies here
+}
+
+androidx {
+    name = "Android for Cars App Library AAOS Extension"
+    type = LibraryType.PUBLISHED_LIBRARY
+    mavenGroup = LibraryGroups.CAR_APP
+    inceptionYear = "2021"
+    description = "AAOS specific funationaltiy to build navigation, parking, and charging apps for cars"
+}
diff --git a/car/app/app-aaos/lint-baseline.xml b/car/app/app-aaos/lint-baseline.xml
new file mode 100644
index 0000000..8f1aa4b
--- /dev/null
+++ b/car/app/app-aaos/lint-baseline.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.2.0-beta02" client="gradle" variant="debug" version="4.2.0-beta02">
+
+</issues>
diff --git a/car/app/app-aaos/src/androidTest/AndroidManifest.xml b/car/app/app-aaos/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..3a56865
--- /dev/null
+++ b/car/app/app-aaos/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.car.app.aaos.test">
+
+</manifest>
diff --git a/car/app/app-aaos/src/main/AndroidManifest.xml b/car/app/app-aaos/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c562b9f
--- /dev/null
+++ b/car/app/app-aaos/src/main/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.car.app.aaos">
+
+</manifest>
\ No newline at end of file
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index 6312144..3b3a9a4 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -172,7 +172,7 @@
     method public androidx.car.app.model.CarText? getTitle();
     method public int getType();
     method public boolean isStandard();
-    method public androidx.car.app.model.Action.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Action.Builder newBuilder();
     method public static String typeToString(int);
     field public static final androidx.car.app.model.Action APP_ICON;
     field public static final androidx.car.app.model.Action BACK;
@@ -236,7 +236,7 @@
     method public androidx.core.graphics.drawable.IconCompat? getIcon();
     method public androidx.car.app.model.CarColor? getTint();
     method public int getType();
-    method public androidx.car.app.model.CarIcon.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.CarIcon.Builder newBuilder();
     field public static final androidx.car.app.model.CarIcon ALERT;
     field public static final androidx.car.app.model.CarIcon APP_ICON;
     field public static final androidx.car.app.model.CarIcon BACK;
@@ -251,6 +251,7 @@
 
   public static final class CarIcon.Builder {
     ctor public CarIcon.Builder(androidx.core.graphics.drawable.IconCompat);
+    ctor public CarIcon.Builder(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.CarIcon build();
     method public androidx.car.app.model.CarIcon.Builder setTint(androidx.car.app.model.CarColor?);
   }
@@ -457,13 +458,14 @@
   public class Metadata {
     method public static androidx.car.app.model.Metadata.Builder builder();
     method public androidx.car.app.model.Place? getPlace();
-    method public androidx.car.app.model.Metadata.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Metadata.Builder newBuilder();
     method public static androidx.car.app.model.Metadata ofPlace(androidx.car.app.model.Place);
     field public static final androidx.car.app.model.Metadata EMPTY_METADATA;
   }
 
   public static final class Metadata.Builder {
     ctor public Metadata.Builder();
+    ctor public Metadata.Builder(androidx.car.app.model.Metadata);
     method public androidx.car.app.model.Metadata build();
     method public androidx.car.app.model.Metadata.Builder setPlace(androidx.car.app.model.Place?);
   }
@@ -532,11 +534,12 @@
     method public static androidx.car.app.model.Place.Builder builder(androidx.car.app.model.LatLng);
     method public androidx.car.app.model.LatLng getLatLng();
     method public androidx.car.app.model.PlaceMarker? getMarker();
-    method public androidx.car.app.model.Place.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Place.Builder newBuilder();
   }
 
   public static final class Place.Builder {
     ctor public Place.Builder(androidx.car.app.model.LatLng);
+    ctor public Place.Builder(androidx.car.app.model.Place);
     method public androidx.car.app.model.Place build();
     method public androidx.car.app.model.Place.Builder setLatLng(androidx.car.app.model.LatLng);
     method public androidx.car.app.model.Place.Builder setMarker(androidx.car.app.model.PlaceMarker?);
@@ -929,7 +932,6 @@
     method public androidx.car.app.model.CarIcon? getLanesImage();
     method public androidx.car.app.navigation.model.Maneuver? getManeuver();
     method public androidx.car.app.model.CarText? getRoad();
-    method public androidx.car.app.navigation.model.Step.Builder newBuilder();
   }
 
   public static final class Step.Builder {
diff --git a/car/app/app/api/public_plus_experimental_current.txt b/car/app/app/api/public_plus_experimental_current.txt
index 6312144..3b3a9a4 100644
--- a/car/app/app/api/public_plus_experimental_current.txt
+++ b/car/app/app/api/public_plus_experimental_current.txt
@@ -172,7 +172,7 @@
     method public androidx.car.app.model.CarText? getTitle();
     method public int getType();
     method public boolean isStandard();
-    method public androidx.car.app.model.Action.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Action.Builder newBuilder();
     method public static String typeToString(int);
     field public static final androidx.car.app.model.Action APP_ICON;
     field public static final androidx.car.app.model.Action BACK;
@@ -236,7 +236,7 @@
     method public androidx.core.graphics.drawable.IconCompat? getIcon();
     method public androidx.car.app.model.CarColor? getTint();
     method public int getType();
-    method public androidx.car.app.model.CarIcon.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.CarIcon.Builder newBuilder();
     field public static final androidx.car.app.model.CarIcon ALERT;
     field public static final androidx.car.app.model.CarIcon APP_ICON;
     field public static final androidx.car.app.model.CarIcon BACK;
@@ -251,6 +251,7 @@
 
   public static final class CarIcon.Builder {
     ctor public CarIcon.Builder(androidx.core.graphics.drawable.IconCompat);
+    ctor public CarIcon.Builder(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.CarIcon build();
     method public androidx.car.app.model.CarIcon.Builder setTint(androidx.car.app.model.CarColor?);
   }
@@ -457,13 +458,14 @@
   public class Metadata {
     method public static androidx.car.app.model.Metadata.Builder builder();
     method public androidx.car.app.model.Place? getPlace();
-    method public androidx.car.app.model.Metadata.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Metadata.Builder newBuilder();
     method public static androidx.car.app.model.Metadata ofPlace(androidx.car.app.model.Place);
     field public static final androidx.car.app.model.Metadata EMPTY_METADATA;
   }
 
   public static final class Metadata.Builder {
     ctor public Metadata.Builder();
+    ctor public Metadata.Builder(androidx.car.app.model.Metadata);
     method public androidx.car.app.model.Metadata build();
     method public androidx.car.app.model.Metadata.Builder setPlace(androidx.car.app.model.Place?);
   }
@@ -532,11 +534,12 @@
     method public static androidx.car.app.model.Place.Builder builder(androidx.car.app.model.LatLng);
     method public androidx.car.app.model.LatLng getLatLng();
     method public androidx.car.app.model.PlaceMarker? getMarker();
-    method public androidx.car.app.model.Place.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Place.Builder newBuilder();
   }
 
   public static final class Place.Builder {
     ctor public Place.Builder(androidx.car.app.model.LatLng);
+    ctor public Place.Builder(androidx.car.app.model.Place);
     method public androidx.car.app.model.Place build();
     method public androidx.car.app.model.Place.Builder setLatLng(androidx.car.app.model.LatLng);
     method public androidx.car.app.model.Place.Builder setMarker(androidx.car.app.model.PlaceMarker?);
@@ -929,7 +932,6 @@
     method public androidx.car.app.model.CarIcon? getLanesImage();
     method public androidx.car.app.navigation.model.Maneuver? getManeuver();
     method public androidx.car.app.model.CarText? getRoad();
-    method public androidx.car.app.navigation.model.Step.Builder newBuilder();
   }
 
   public static final class Step.Builder {
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index 6312144..3b3a9a4 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -172,7 +172,7 @@
     method public androidx.car.app.model.CarText? getTitle();
     method public int getType();
     method public boolean isStandard();
-    method public androidx.car.app.model.Action.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Action.Builder newBuilder();
     method public static String typeToString(int);
     field public static final androidx.car.app.model.Action APP_ICON;
     field public static final androidx.car.app.model.Action BACK;
@@ -236,7 +236,7 @@
     method public androidx.core.graphics.drawable.IconCompat? getIcon();
     method public androidx.car.app.model.CarColor? getTint();
     method public int getType();
-    method public androidx.car.app.model.CarIcon.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.CarIcon.Builder newBuilder();
     field public static final androidx.car.app.model.CarIcon ALERT;
     field public static final androidx.car.app.model.CarIcon APP_ICON;
     field public static final androidx.car.app.model.CarIcon BACK;
@@ -251,6 +251,7 @@
 
   public static final class CarIcon.Builder {
     ctor public CarIcon.Builder(androidx.core.graphics.drawable.IconCompat);
+    ctor public CarIcon.Builder(androidx.car.app.model.CarIcon);
     method public androidx.car.app.model.CarIcon build();
     method public androidx.car.app.model.CarIcon.Builder setTint(androidx.car.app.model.CarColor?);
   }
@@ -457,13 +458,14 @@
   public class Metadata {
     method public static androidx.car.app.model.Metadata.Builder builder();
     method public androidx.car.app.model.Place? getPlace();
-    method public androidx.car.app.model.Metadata.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Metadata.Builder newBuilder();
     method public static androidx.car.app.model.Metadata ofPlace(androidx.car.app.model.Place);
     field public static final androidx.car.app.model.Metadata EMPTY_METADATA;
   }
 
   public static final class Metadata.Builder {
     ctor public Metadata.Builder();
+    ctor public Metadata.Builder(androidx.car.app.model.Metadata);
     method public androidx.car.app.model.Metadata build();
     method public androidx.car.app.model.Metadata.Builder setPlace(androidx.car.app.model.Place?);
   }
@@ -532,11 +534,12 @@
     method public static androidx.car.app.model.Place.Builder builder(androidx.car.app.model.LatLng);
     method public androidx.car.app.model.LatLng getLatLng();
     method public androidx.car.app.model.PlaceMarker? getMarker();
-    method public androidx.car.app.model.Place.Builder newBuilder();
+    method @Deprecated public androidx.car.app.model.Place.Builder newBuilder();
   }
 
   public static final class Place.Builder {
     ctor public Place.Builder(androidx.car.app.model.LatLng);
+    ctor public Place.Builder(androidx.car.app.model.Place);
     method public androidx.car.app.model.Place build();
     method public androidx.car.app.model.Place.Builder setLatLng(androidx.car.app.model.LatLng);
     method public androidx.car.app.model.Place.Builder setMarker(androidx.car.app.model.PlaceMarker?);
@@ -929,7 +932,6 @@
     method public androidx.car.app.model.CarIcon? getLanesImage();
     method public androidx.car.app.navigation.model.Maneuver? getManeuver();
     method public androidx.car.app.model.CarText? getRoad();
-    method public androidx.car.app.navigation.model.Step.Builder newBuilder();
   }
 
   public static final class Step.Builder {
diff --git a/car/app/app/src/main/java/androidx/car/app/model/Action.java b/car/app/app/src/main/java/androidx/car/app/model/Action.java
index 3989dad..35d2146 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/Action.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/Action.java
@@ -144,8 +144,12 @@
     /**
      * Returns a {@link Builder} instance configured with the same data as this {@link Action}
      * instance.
+     *
+     * @deprecated use constructor.
      */
+    // TODO(b/177484889): remove once host is changed to use new public ctor.
     @NonNull
+    @Deprecated
     public Builder newBuilder() {
         return new Builder(this);
     }
@@ -405,7 +409,13 @@
         public Builder() {
         }
 
-        Builder(Action action) {
+        /**
+         * Returns a {@link Builder} instance configured with the same data as the given
+         * {@link Action} instance.
+         *
+         * @throws NullPointerException if {@code icon} is {@code null}.
+         */
+        Builder(@NonNull Action action) {
             mTitle = action.getTitle();
             mIcon = action.getIcon();
             mBackgroundColor = action.getBackgroundColor();
diff --git a/car/app/app/src/main/java/androidx/car/app/model/CarIcon.java b/car/app/app/src/main/java/androidx/car/app/model/CarIcon.java
index 008ba2a..b858168 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/CarIcon.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/CarIcon.java
@@ -212,7 +212,10 @@
     /**
      * Returns a {@link Builder} instance configured with the same data as this {@link CarIcon}
      * instance.
+     * @deprecated use constructor.
      */
+    // TODO(b/177484889): remove once host is changed to use new public ctor.
+    @Deprecated
     @NonNull
     public Builder newBuilder() {
         return new Builder(this);
@@ -427,7 +430,14 @@
             mTint = null;
         }
 
-        Builder(@NonNull CarIcon carIcon) {
+        /**
+         * Returns a {@link Builder} instance configured with the same data as the given
+         * {@link CarIcon} instance.
+         *
+         * @throws NullPointerException if {@code icon} is {@code null}.
+         */
+        public Builder(@NonNull CarIcon carIcon) {
+            requireNonNull(carIcon);
             mType = carIcon.getType();
             mIcon = carIcon.getIcon();
             mTint = carIcon.getTint();
diff --git a/car/app/app/src/main/java/androidx/car/app/model/Metadata.java b/car/app/app/src/main/java/androidx/car/app/model/Metadata.java
index f5e152b..8894213 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/Metadata.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/Metadata.java
@@ -51,7 +51,12 @@
         return new Builder().setPlace(requireNonNull(place)).build();
     }
 
-    /** Returns a new {@link Builder} with the data from this {@link Metadata} instance. */
+    /**
+     * Returns a new {@link Builder} with the data from this {@link Metadata} instance.
+     * @deprecated use constructor.
+     */
+    // TODO(b/177484889): remove once host is changed to use new public ctor.
+    @Deprecated
     @NonNull
     public Builder newBuilder() {
         return new Builder(this);
@@ -117,8 +122,13 @@
         public Builder() {
         }
 
-        Builder(Metadata metadata) {
-            this.mPlace = metadata.getPlace();
+        /**
+         * Returns a new {@link Builder} with the data from the given {@link Metadata} instance.
+         *
+         * @throws NullPointerException if {@code icon} is {@code null}.
+         */
+        public Builder(@NonNull Metadata metadata) {
+            this.mPlace = requireNonNull(metadata).getPlace();
         }
     }
 }
diff --git a/car/app/app/src/main/java/androidx/car/app/model/Place.java b/car/app/app/src/main/java/androidx/car/app/model/Place.java
index 2932e24..771f4f6 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/Place.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/Place.java
@@ -45,8 +45,13 @@
         return new Builder(requireNonNull(latLng));
     }
 
-    /** Returns a {@link Builder} instance with the same data as this {@link Place} instance. */
+    /**
+     * Returns a {@link Builder} instance with the same data as this {@link Place} instance.
+     * @deprecated use constructor.
+     */
+    // TODO(b/177484889): remove once host is changed to use new public ctor.
     @NonNull
+    @Deprecated
     public Builder newBuilder() {
         return new Builder(this);
     }
@@ -113,7 +118,12 @@
             mLatLng = latLng;
         }
 
-        Builder(Place place) {
+        /**
+         * Returns a {@link Builder} instance with the same data as the given {@link Place}
+         * instance.
+         */
+        public Builder(@NonNull Place place) {
+            requireNonNull(place);
             mLatLng = place.getLatLng();
             mMarker = place.getMarker();
         }
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java
index 8d9c01d..0745a1b 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/ActionsConstraints.java
@@ -19,6 +19,8 @@
 
 import static androidx.annotation.RestrictTo.Scope;
 
+import static java.util.Objects.requireNonNull;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
@@ -59,13 +61,13 @@
      */
     @NonNull
     public static final ActionsConstraints ACTIONS_CONSTRAINTS_SIMPLE =
-            ACTIONS_CONSTRAINTS_CONSERVATIVE.newBuilder().setMaxCustomTitles(1).build();
+            new ActionsConstraints.Builder(ACTIONS_CONSTRAINTS_CONSERVATIVE).setMaxCustomTitles(
+                    1).build();
 
     /** Constraints for navigation templates. */
     @NonNull
     public static final ActionsConstraints ACTIONS_CONSTRAINTS_NAVIGATION =
-            ACTIONS_CONSTRAINTS_CONSERVATIVE
-                    .newBuilder()
+            new ActionsConstraints.Builder(ACTIONS_CONSTRAINTS_CONSERVATIVE)
                     .setMaxActions(4)
                     .setMaxCustomTitles(1)
                     .addRequiredActionType(Action.TYPE_CUSTOM)
@@ -84,16 +86,6 @@
         return new Builder();
     }
 
-    /**
-     * Returns a new builder that contains the same data as this {@link ActionsConstraints}
-     * instance.
-     */
-    @VisibleForTesting
-    @NonNull
-    public Builder newBuilder() {
-        return new Builder(this);
-    }
-
     /** Returns the max number of actions allowed. */
     public int getMaxActions() {
         return mMaxActions;
@@ -239,7 +231,14 @@
         public Builder() {
         }
 
-        Builder(ActionsConstraints constraints) {
+        /**
+         * Returns a new builder that contains the same data as the given {@link ActionsConstraints}
+         * instance.
+         *
+         * @throws NullPointerException if {@code latLng} is {@code null}.
+         */
+        public Builder(@NonNull ActionsConstraints constraints) {
+            requireNonNull(constraints);
             this.mMaxActions = constraints.getMaxActions();
             this.mMaxCustomTitles = constraints.getMaxCustomTitles();
             this.mRequiredActionTypes.addAll(constraints.getRequiredActionTypes());
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/RowConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/RowConstraints.java
index 685cf14..e88c148 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/RowConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/RowConstraints.java
@@ -16,6 +16,8 @@
 
 package androidx.car.app.model.constraints;
 
+import static java.util.Objects.requireNonNull;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.car.app.model.CarIcon;
@@ -67,7 +69,7 @@
     /** The constraints for a full-width row in a list (simple + toggle support). */
     @NonNull
     public static final RowConstraints ROW_CONSTRAINTS_FULL_LIST =
-            ROW_CONSTRAINTS_SIMPLE.newBuilder().setToggleAllowed(true).build();
+            new RowConstraints.Builder(ROW_CONSTRAINTS_SIMPLE).setToggleAllowed(true).build();
 
     private final int mMaxTextLinesPerRow;
     private final int mMaxActionsExclusive;
@@ -85,14 +87,6 @@
         return new Builder();
     }
 
-    /**
-     * Returns a new builder that contains the same data as this {@link RowConstraints} instance.
-     */
-    @NonNull
-    public Builder newBuilder() {
-        return new Builder(this);
-    }
-
     /** Returns whether the row can have a click listener associated with it. */
     public boolean isOnClickListenerAllowed() {
         return mIsOnClickListenerAllowed;
@@ -225,10 +219,17 @@
         }
 
         /** Returns an empty {@link Builder} instance. */
-        Builder() {
+        public Builder() {
         }
 
-        Builder(RowConstraints constraints) {
+        /**
+         * Returns a new builder that contains the same data as the given {@link RowConstraints}
+         * instance.
+         *
+         * @throws NullPointerException if {@code latLng} is {@code null}.
+         */
+        public Builder(@NonNull RowConstraints constraints) {
+            requireNonNull(constraints);
             mIsOnClickListenerAllowed = constraints.isOnClickListenerAllowed();
             mMaxTextLines = constraints.getMaxTextLinesPerRow();
             mMaxActionsExclusive = constraints.getMaxActionsExclusive();
diff --git a/car/app/app/src/main/java/androidx/car/app/model/constraints/RowListConstraints.java b/car/app/app/src/main/java/androidx/car/app/model/constraints/RowListConstraints.java
index d0b1464..e4bbcf5 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/constraints/RowListConstraints.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/constraints/RowListConstraints.java
@@ -21,6 +21,8 @@
 import static androidx.car.app.model.constraints.RowConstraints.ROW_CONSTRAINTS_PANE;
 import static androidx.car.app.model.constraints.RowConstraints.ROW_CONSTRAINTS_SIMPLE;
 
+import static java.util.Objects.requireNonNull;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
 import androidx.car.app.model.Action;
@@ -50,8 +52,7 @@
     /** Default constraints for heterogeneous pane of items, full width. */
     @NonNull
     public static final RowListConstraints ROW_LIST_CONSTRAINTS_PANE =
-            ROW_LIST_CONSTRAINTS_CONSERVATIVE
-                    .newBuilder()
+            new RowListConstraints.Builder(ROW_LIST_CONSTRAINTS_CONSERVATIVE)
                     .setMaxActions(2)
                     .setRowConstraints(ROW_CONSTRAINTS_PANE)
                     .setAllowSelectableLists(false)
@@ -60,16 +61,14 @@
     /** Default constraints for uniform lists of items, no toggles. */
     @NonNull
     public static final RowListConstraints ROW_LIST_CONSTRAINTS_SIMPLE =
-            ROW_LIST_CONSTRAINTS_CONSERVATIVE
-                    .newBuilder()
+            new RowListConstraints.Builder(ROW_LIST_CONSTRAINTS_CONSERVATIVE)
                     .setRowConstraints(ROW_CONSTRAINTS_SIMPLE)
                     .build();
 
     /** Default constraints for the route preview card. */
     @NonNull
     public static final RowListConstraints ROW_LIST_CONSTRAINTS_ROUTE_PREVIEW =
-            ROW_LIST_CONSTRAINTS_CONSERVATIVE
-                    .newBuilder()
+            new RowListConstraints.Builder(ROW_LIST_CONSTRAINTS_CONSERVATIVE)
                     .setRowConstraints(ROW_CONSTRAINTS_SIMPLE)
                     .setAllowSelectableLists(true)
                     .build();
@@ -77,8 +76,7 @@
     /** Default constraints for uniform lists of items, full width (simple + toggle support). */
     @NonNull
     public static final RowListConstraints ROW_LIST_CONSTRAINTS_FULL_LIST =
-            ROW_LIST_CONSTRAINTS_CONSERVATIVE
-                    .newBuilder()
+            new RowListConstraints.Builder(ROW_LIST_CONSTRAINTS_CONSERVATIVE)
                     .setRowConstraints(ROW_CONSTRAINTS_FULL_LIST)
                     .setAllowSelectableLists(true)
                     .build();
@@ -94,12 +92,6 @@
         return new Builder();
     }
 
-    /** Return a a new builder for this {@link RowListConstraints} instance. */
-    @NonNull
-    public Builder newBuilder() {
-        return new Builder(this);
-    }
-
     /** Returns the maximum number of actions allowed to be added alongside the list. */
     public int getMaxActions() {
         return mMaxActions;
@@ -220,7 +212,13 @@
         public Builder() {
         }
 
-        Builder(RowListConstraints constraints) {
+        /**
+         * Return a a new builder for the given {@link RowListConstraints} instance.
+         *
+         * @throws NullPointerException if {@code latLng} is {@code null}.
+         */
+        public Builder(@NonNull RowListConstraints constraints) {
+            requireNonNull(constraints);
             this.mMaxActions = constraints.getMaxActions();
             this.mRowConstraints = constraints.getRowConstraints();
             this.mAllowSelectableLists = constraints.isAllowSelectableLists();
diff --git a/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java b/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java
index 867f254..dbdc5b4 100644
--- a/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java
+++ b/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java
@@ -71,34 +71,42 @@
     }
 
     /**
-     * Returns a new {@link Builder} instance configured with the same data as this {@link Step}
-     * instance.
+     * Returns the maneuver to be performed on this step or {@code null} if this step doesn't
+     * involve a maneuver.
      */
-    @NonNull
-    public Builder newBuilder() {
-        return new Builder(this);
-    }
-
     @Nullable
     public Maneuver getManeuver() {
         return mManeuver;
     }
 
+    /**
+     * Returns a list of {@link Lane} that contains information of the road lanes at the point
+     * where the driver should execute this step.
+     */
     @NonNull
     public List<Lane> getLanes() {
         return CollectionUtils.emptyIfNull(mLanes);
     }
 
+    /**
+     * Returns the image representing all the lanes or {@code null} if no lanes image is available.
+     */
     @Nullable
     public CarIcon getLanesImage() {
         return mLanesImage;
     }
 
+    /**
+     * Returns the text description of this maneuver.
+     */
     @Nullable
     public CarText getCue() {
         return mCue;
     }
 
+    /**
+     * Returns the text description of the road for the step or {@code null} if unknown.
+     */
     @Nullable
     public CarText getRoad() {
         return mRoad;
@@ -179,12 +187,10 @@
          * Constructs a new builder of {@link Step} with a cue.
          *
          * <p>A cue must always be set when the step is created and is used as a fallback when
-         * {@link
-         * Maneuver} is not set or is unavailable.
+         * {@link Maneuver} is not set or is unavailable.
          *
          * <p>Some cluster displays do not support UTF-8 encoded characters, in which case
-         * unsupported
-         * characters will not be displayed properly.
+         * unsupported characters will not be displayed properly.
          *
          * @throws NullPointerException if {@code cue} is {@code null}.
          * @see Builder#setCue(CharSequence)
@@ -193,19 +199,9 @@
             this.mCue = CarText.create(requireNonNull(cue));
         }
 
-        Builder(Step step) {
-            this.mManeuver = step.getManeuver();
-            this.mLanes.clear();
-            this.mLanes.addAll(step.getLanes());
-            this.mLanesImage = step.getLanesImage();
-            this.mCue = requireNonNull(step.getCue());
-            this.mRoad = step.getRoad();
-        }
-
         /**
          * Sets the maneuver to be performed on this step or {@code null} if this step doesn't
-         * involve a
-         * maneuver.
+         * involve a maneuver.
          */
         @NonNull
         public Builder setManeuver(@Nullable Maneuver maneuver) {
@@ -312,8 +308,7 @@
          * Sets a text description of the road for the step or {@code null} if unknown.
          *
          * <p>This value is primarily used for vehicle cluster and heads-up displays and may not
-         * appear
-         * in the navigation template.
+         * appear in the navigation template.
          *
          * <p>For example, a {@link Step} for a left turn might provide "State Street" for the road.
          *
diff --git a/car/app/app/src/test/java/androidx/car/app/model/ActionTest.java b/car/app/app/src/test/java/androidx/car/app/model/ActionTest.java
index 414e404..8232f95 100644
--- a/car/app/app/src/test/java/androidx/car/app/model/ActionTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/model/ActionTest.java
@@ -135,34 +135,6 @@
     }
 
     @Test
-    public void create_invalidSetOnBackThrows() {
-        assertThrows(
-                IllegalStateException.class,
-                () -> Action.BACK.newBuilder().setOnClickListener(() -> {
-                }).build());
-        assertThrows(
-                IllegalStateException.class,
-                () -> Action.BACK.newBuilder().setTitle("BACK").build());
-        assertThrows(
-                IllegalStateException.class,
-                () -> Action.BACK.newBuilder().setIcon(CarIcon.ALERT).build());
-    }
-
-    @Test
-    public void create_invalidSetOnAppIconThrows() {
-        assertThrows(
-                IllegalStateException.class,
-                () -> Action.APP_ICON.newBuilder().setOnClickListener(() -> {
-                }).build());
-        assertThrows(
-                IllegalStateException.class,
-                () -> Action.APP_ICON.newBuilder().setTitle("APP").build());
-        assertThrows(
-                IllegalStateException.class,
-                () -> Action.APP_ICON.newBuilder().setIcon(CarIcon.ALERT).build());
-    }
-
-    @Test
     public void equals() {
         String title = "foo";
         CarIcon icon = CarIcon.ALERT;
diff --git a/car/app/app/src/test/java/androidx/car/app/model/CarIconTest.java b/car/app/app/src/test/java/androidx/car/app/model/CarIconTest.java
index 79f15fb..ef80907 100644
--- a/car/app/app/src/test/java/androidx/car/app/model/CarIconTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/model/CarIconTest.java
@@ -77,7 +77,7 @@
 
     @Test
     public void newBuilder_fromStandard() {
-        CarIcon carIcon = BACK.newBuilder().setTint(GREEN).build();
+        CarIcon carIcon = new CarIcon.Builder(BACK).setTint(GREEN).build();
 
         assertThat(carIcon.getType()).isEqualTo(TYPE_BACK);
         assertThat(carIcon.getTint()).isEqualTo(GREEN);
@@ -144,6 +144,6 @@
 
     @Test
     public void notEquals() {
-        assertThat(BACK.newBuilder().setTint(GREEN).build()).isNotEqualTo(BACK);
+        assertThat(new CarIcon.Builder(BACK).setTint(GREEN).build()).isNotEqualTo(BACK);
     }
 }
diff --git a/compose/animation/animation-core/api/current.txt b/compose/animation/animation-core/api/current.txt
index df76239..89beb5f 100644
--- a/compose/animation/animation-core/api/current.txt
+++ b/compose/animation/animation-core/api/current.txt
@@ -36,18 +36,26 @@
   }
 
   public final class AnimateAsStateKt {
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static <T extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T targetValue, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.DpOffset> animateAsState-4E4yWWY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.DpOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.DpOffset,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateBoundsAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateDpAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateFloatAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateIntAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateIntOffsetAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateIntSizeAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateOffsetAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateRectAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateSizeAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateValueAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
   }
 
   public abstract class AnimatedFloat extends androidx.compose.animation.core.BaseAnimatedValue<java.lang.Float,androidx.compose.animation.core.AnimationVector1D> {
diff --git a/compose/animation/animation-core/api/public_plus_experimental_current.txt b/compose/animation/animation-core/api/public_plus_experimental_current.txt
index df76239..89beb5f 100644
--- a/compose/animation/animation-core/api/public_plus_experimental_current.txt
+++ b/compose/animation/animation-core/api/public_plus_experimental_current.txt
@@ -36,18 +36,26 @@
   }
 
   public final class AnimateAsStateKt {
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static <T extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T targetValue, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.DpOffset> animateAsState-4E4yWWY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.DpOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.DpOffset,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateBoundsAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateDpAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateFloatAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateIntAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateIntOffsetAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateIntSizeAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateOffsetAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateRectAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateSizeAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateValueAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
   }
 
   public abstract class AnimatedFloat extends androidx.compose.animation.core.BaseAnimatedValue<java.lang.Float,androidx.compose.animation.core.AnimationVector1D> {
diff --git a/compose/animation/animation-core/api/restricted_current.txt b/compose/animation/animation-core/api/restricted_current.txt
index 6f1cc23b..cafee25 100644
--- a/compose/animation/animation-core/api/restricted_current.txt
+++ b/compose/animation/animation-core/api/restricted_current.txt
@@ -36,18 +36,26 @@
   }
 
   public final class AnimateAsStateKt {
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static <T extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T targetValue, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.DpOffset> animateAsState-4E4yWWY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.DpOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.DpOffset,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Bounds> animateBoundsAsState(androidx.compose.ui.unit.Bounds targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.Dp> animateDpAsState-Lz7ev7o(float targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Float> animateFloatAsState(float targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional float visibilityThreshold, optional kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.lang.Integer> animateIntAsState(int targetValue, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animationSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntOffset> animateIntOffsetAsState-2AXSKHY(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.unit.IntSize> animateIntSizeAsState-Cmzki-s(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Offset> animateOffsetAsState-t81mtYE(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Rect> animateRectAsState(androidx.compose.ui.geometry.Rect targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.geometry.Size> animateSizeAsState-rlPqr8Y(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> androidx.compose.runtime.State<T> animateValueAsState(T? targetValue, androidx.compose.animation.core.TwoWayConverter<T,V> typeConverter, optional androidx.compose.animation.core.AnimationSpec<T> animationSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? finishedListener);
   }
 
   public abstract class AnimatedFloat extends androidx.compose.animation.core.BaseAnimatedValue<java.lang.Float,androidx.compose.animation.core.AnimationVector1D> {
diff --git a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/AnimatedValueSamples.kt b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/AnimatedValueSamples.kt
index d2a677c..31eeda6 100644
--- a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/AnimatedValueSamples.kt
+++ b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/AnimatedValueSamples.kt
@@ -19,7 +19,11 @@
 import androidx.annotation.Sampled
 import androidx.compose.animation.core.AnimationVector2D
 import androidx.compose.animation.core.TwoWayConverter
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateValueAsState
+import androidx.compose.animation.core.animateDpAsState
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.animateIntOffsetAsState
+import androidx.compose.animation.core.animateOffsetAsState
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -45,7 +49,7 @@
         // This [animateState] returns a State<Float> object. The value of the State object is
         // being updated by animation. (This method is overloaded for different parameter types.)
         // Here we use the returned [State] object as a property delegate.
-        val alpha: Float by animateAsState(if (visible) 1f else 0f)
+        val alpha: Float by animateFloatAsState(if (visible) 1f else 0f)
         Box(modifier = Modifier.background(Color.Red).alpha(alpha))
     }
 }
@@ -69,9 +73,9 @@
         // Animates a custom type value to the given target value, using a [TwoWayConverter]. The
         // converter tells the animation system how to convert the custom type from and to
         // [AnimationVector], so that it can be animated.
-        val animSize: MySize by animateAsState<MySize, AnimationVector2D>(
+        val animSize: MySize by animateValueAsState(
             mySize,
-            TwoWayConverter(
+            TwoWayConverter<MySize, AnimationVector2D>(
                 convertToVector = { AnimationVector2D(it.width.value, it.height.value) },
                 convertFromVector = { MySize(it.v1.dp, it.v2.dp) }
             )
@@ -86,7 +90,7 @@
     @Composable
     fun HeightAnimation(collapsed: Boolean) {
         // Animates a height of [Dp] type to different target values based on the [collapsed] flag.
-        val height: Dp by animateAsState(if (collapsed) 10.dp else 20.dp)
+        val height: Dp by animateDpAsState(if (collapsed) 10.dp else 20.dp)
         Box(Modifier.fillMaxWidth().height(height).background(color = Color.Red))
     }
 }
@@ -98,15 +102,16 @@
     @Composable
     fun OffsetAnimation(selected: Boolean) {
         // Animates the offset depending on the selected flag.
-        // [animateAsState] returns a State<Offset> object. The value of the State object is
+        // [animateOffsetAsState] returns a State<Offset> object. The value of the State object is
         // updated by the animation. Here we use that State<Offset> as a property delegate.
-        val offset: Offset by animateAsState(
+        val offset: Offset by animateOffsetAsState(
             if (selected) Offset(0f, 0f) else Offset(20f, 20f)
         )
 
-        // In this example, animateAsState returns a State<IntOffset>. The value of the returned
+        // In this example, animateIntOffsetAsState returns a State<IntOffset>. The value of the
+        // returned
         // State object is updated by the animation.
-        val intOffset: IntOffset by animateAsState(
+        val intOffset: IntOffset by animateIntOffsetAsState(
             if (selected) IntOffset(0, 0) else IntOffset(50, 50)
         )
     }
diff --git a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/InfiniteTransitionSamples.kt b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/InfiniteTransitionSamples.kt
index d01dc7c..1977ca9 100644
--- a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/InfiniteTransitionSamples.kt
+++ b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/InfiniteTransitionSamples.kt
@@ -83,7 +83,8 @@
         Box(Modifier.fillMaxSize()) {
             Icon(
                 Icons.Filled.Favorite,
-                Modifier.align(Alignment.Center)
+                contentDescription = null,
+                modifier = Modifier.align(Alignment.Center)
                     .graphicsLayer(
                         scaleX = scale,
                         scaleY = scale
diff --git a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/SuspendAnimationSamples.kt b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/SuspendAnimationSamples.kt
index 43d0a9e..01fb138 100644
--- a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/SuspendAnimationSamples.kt
+++ b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/SuspendAnimationSamples.kt
@@ -93,7 +93,8 @@
         Box(Modifier.fillMaxSize()) {
             Icon(
                 Icons.Filled.Favorite,
-                Modifier.align(Alignment.Center)
+                contentDescription = null,
+                modifier = Modifier.align(Alignment.Center)
                     .graphicsLayer(
                         scaleX = 3.0f,
                         scaleY = 3.0f,
diff --git a/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/SingleValueAnimationTest.kt b/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/SingleValueAnimationTest.kt
index e58f68a..31b6963 100644
--- a/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/SingleValueAnimationTest.kt
+++ b/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/SingleValueAnimationTest.kt
@@ -16,7 +16,7 @@
 
 package androidx.compose.animation.core
 
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.dispatch.withFrameNanos
@@ -31,7 +31,6 @@
 import androidx.compose.ui.test.ExperimentalTestApi
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.Bounds
-import androidx.compose.ui.unit.DpOffset
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.lerp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -60,7 +59,7 @@
         var enabled by mutableStateOf(false)
         rule.setContent {
             Box {
-                val animationValue by animateAsState(
+                val animationValue by animateDpAsState(
                     if (enabled) 50.dp else 250.dp, myTween()
                 )
                 // TODO: Properly test this with a deterministic clock when the test framework is
@@ -93,7 +92,7 @@
         rule.setContent {
             Box {
                 // Animate from 250f to 50f when enable flips to true
-                val animationValue by animateAsState(
+                val animationValue by animateFloatAsState(
                     if (enabled) 50f else 250f, tween(200, easing = FastOutLinearInEasing)
                 )
                 // TODO: Properly test this with a deterministic clock when the test framework is
@@ -135,20 +134,7 @@
         var enabled by mutableStateOf(false)
         rule.setContent {
             Box {
-                val vectorValue by animateAsState(
-                    if (enabled) endVal else startVal,
-                    tween()
-                )
-
-                val positionValue by animateAsState(
-                    if (enabled)
-                        DpOffset.VectorConverter.convertFromVector(endVal)
-                    else
-                        DpOffset.VectorConverter.convertFromVector(startVal),
-                    tween()
-                )
-
-                val sizeValue by animateAsState(
+                val sizeValue by animateSizeAsState(
                     if (enabled)
                         Size.VectorConverter.convertFromVector(endVal)
                     else
@@ -156,7 +142,7 @@
                     tween()
                 )
 
-                val pxPositionValue by animateAsState(
+                val pxPositionValue by animateOffsetAsState(
                     if (enabled)
                         Offset.VectorConverter.convertFromVector(endVal)
                     else
@@ -175,13 +161,8 @@
                                 lerp(startVal.v2, endVal.v2, playTime / 100f)
                             )
 
-                            assertEquals(expect, vectorValue)
                             assertEquals(Size.VectorConverter.convertFromVector(expect), sizeValue)
                             assertEquals(
-                                DpOffset.VectorConverter.convertFromVector(expect),
-                                positionValue
-                            )
-                            assertEquals(
                                 Offset.VectorConverter.convertFromVector(expect),
                                 pxPositionValue
                             )
@@ -210,12 +191,7 @@
         var enabled by mutableStateOf(false)
         rule.setContent {
             Box {
-                val vectorValue by animateAsState(
-                    if (enabled) endVal else startVal,
-                    tween()
-                )
-
-                val boundsValue by animateAsState(
+                val boundsValue by animateBoundsAsState(
                     if (enabled)
                         Bounds.VectorConverter.convertFromVector(endVal)
                     else
@@ -223,7 +199,7 @@
                     tween()
                 )
 
-                val pxBoundsValue by animateAsState(
+                val pxBoundsValue by animateRectAsState(
                     if (enabled)
                         Rect.VectorConverter.convertFromVector(endVal)
                     else
@@ -246,7 +222,6 @@
                                 lerp(startVal.v4, endVal.v4, fraction)
                             )
 
-                            assertEquals(expect, vectorValue)
                             assertEquals(
                                 Bounds.VectorConverter.convertFromVector(expect),
                                 boundsValue
@@ -280,12 +255,8 @@
         var enabled by mutableStateOf(false)
         rule.setContent {
             Box {
-                val vectorValue by animateAsState(
-                    if (enabled) endVal else startVal,
-                    tween()
-                )
 
-                val boundsValue by animateAsState(
+                val boundsValue by animateBoundsAsState(
                     if (enabled)
                         Bounds.VectorConverter.convertFromVector(endVal)
                     else
@@ -306,7 +277,6 @@
                                 lerp(startVal.v4, endVal.v4, fraction)
                             )
 
-                            assertEquals(expect, vectorValue)
                             assertEquals(
                                 Bounds.VectorConverter.convertFromVector(expect),
                                 boundsValue
@@ -327,7 +297,7 @@
         var enabled by mutableStateOf(false)
         rule.setContent {
             Box {
-                val value by animateAsState(
+                val value by animateColorAsState(
                     if (enabled) Color.Cyan else Color.Black,
                     TweenSpec(
                         durationMillis = 100,
@@ -358,36 +328,29 @@
     fun visibilityThresholdTest() {
 
         val specForFloat = FloatSpringSpec(visibilityThreshold = 0.01f)
-        val specForVector = FloatSpringSpec(visibilityThreshold = 0.5f)
         val specForOffset = FloatSpringSpec(visibilityThreshold = 0.5f)
         val specForBounds = FloatSpringSpec(visibilityThreshold = 0.1f)
 
         var enabled by mutableStateOf(false)
         rule.setContent {
             Box {
-                val vectorValue by animateAsState(
-                    if (enabled) AnimationVector(100f) else AnimationVector(0f),
-                    visibilityThreshold = AnimationVector(0.5f)
-                )
-
-                val offsetValue by animateAsState(
+                val offsetValue by animateOffsetAsState(
                     if (enabled)
                         Offset(100f, 100f)
                     else
                         Offset(0f, 0f)
                 )
 
-                val boundsValue by animateAsState(
+                val boundsValue by animateBoundsAsState(
                     if (enabled)
                         Bounds(100.dp, 100.dp, 100.dp, 100.dp)
                     else
                         Bounds(0.dp, 0.dp, 0.dp, 0.dp)
                 )
 
-                val floatValue by animateAsState(if (enabled) 100f else 0f)
+                val floatValue by animateFloatAsState(if (enabled) 100f else 0f)
 
                 val durationForFloat = specForFloat.getDurationMillis(0f, 100f, 0f)
-                val durationForVector = specForVector.getDurationMillis(0f, 100f, 0f)
                 val durationForOffset = specForOffset.getDurationMillis(0f, 100f, 0f)
                 val durationForBounds = specForBounds.getDurationMillis(0f, 100f, 0f)
 
@@ -400,13 +363,6 @@
                             val expectFloat = specForFloat.getValue(playTime, 0f, 100f, 0f)
                             assertEquals("play time: $playTime", expectFloat, floatValue)
 
-                            if (playTime < durationForVector) {
-                                val expectVector = specForVector.getValue(playTime, 0f, 100f, 0f)
-                                assertEquals(AnimationVector(expectVector), vectorValue)
-                            } else {
-                                assertEquals(AnimationVector(100f), vectorValue)
-                            }
-
                             if (playTime < durationForOffset) {
                                 val expectOffset = specForOffset.getValue(playTime, 0f, 100f, 0f)
                                 assertEquals(Offset(expectOffset, expectOffset), offsetValue)
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt
index 386ddc0..932f7fa 100644
--- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt
@@ -27,7 +27,6 @@
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.unit.Bounds
 import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpOffset
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
 
@@ -40,10 +39,10 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
- * updated by the animation until the animation finishes.
+ * [animateFloatAsState] returns a [State] object. The value of the state object will continuously
+ * be updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateFloatAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedFloat][androidx.compose.animation.animatedFloat] for cancelable
  * animations.
  *
@@ -58,7 +57,7 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateFloatAsState(
     targetValue: Float,
     animationSpec: AnimationSpec<Float> = defaultAnimation,
     visibilityThreshold: Float = 0.01f,
@@ -87,6 +86,27 @@
     return animationState
 }
 
+@Composable
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateFloatAsState(targetValue, animationSpec, visibilityThreshold, " +
+            "finishedListener)",
+        "androidx.compose.animation.core.animateFloatAsState"
+    )
+)
+fun animateAsState(
+    targetValue: Float,
+    animationSpec: AnimationSpec<Float> = defaultAnimation,
+    visibilityThreshold: Float = 0.01f,
+    finishedListener: ((Float) -> Unit)? = null
+): State<Float> = animateFloatAsState(
+    targetValue,
+    animationSpec,
+    visibilityThreshold,
+    finishedListener
+)
+
 /**
  * Fire-and-forget animation function for [Dp]. This Composable function is overloaded for
  * different parameter types such as [Float], [Color][androidx.compose.ui.graphics.Color], [Offset],
@@ -94,10 +114,10 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateDpAsState] returns a [State] object. The value of the state object will continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateDpAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
@@ -110,14 +130,12 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateDpAsState(
     targetValue: Dp,
-    animationSpec: AnimationSpec<Dp> = remember {
-        spring(visibilityThreshold = Dp.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<Dp> = dpDefaultSpring,
     finishedListener: ((Dp) -> Unit)? = null
 ): State<Dp> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue,
         Dp.VectorConverter,
         animationSpec,
@@ -125,41 +143,21 @@
     )
 }
 
-/**
- * Fire-and-forget animation function for [DpOffset]. This Composable function is overloaded for
- * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset],
- * etc. When the provided [targetValue] is changed, the animation will run automatically. If there
- * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
- * course to animate towards the new target value.
- *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
- * updated by the animation until the animation finishes.
- *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
- * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
- * animations.
- *
- *     val position: DpOffset by animateAsState(
- *         if (selected) DpOffset(0.dp, 0.dp) else DpOffset(20.dp, 20.dp))
- *
- * @param targetValue Target value of the animation
- * @param animationSpec The animation that will be used to change the value through time. Physics
- *                    animation will be used by default.
- * @param finishedListener An optional end listener to get notified when the animation is finished.
- * @return A [State] object, the value of which is updated by animation.
- */
+private val dpDefaultSpring = spring<Dp>(visibilityThreshold = Dp.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateDpAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateDpAsState"
+    )
+)
 @Composable
 fun animateAsState(
-    targetValue: DpOffset,
-    animationSpec: AnimationSpec<DpOffset> = remember {
-        spring(visibilityThreshold = DpOffset.VisibilityThreshold)
-    },
-    finishedListener: ((DpOffset) -> Unit)? = null
-): State<DpOffset> {
-    return animateAsState(
-        targetValue, DpOffset.VectorConverter, animationSpec, finishedListener = finishedListener
-    )
-}
+    targetValue: Dp,
+    animationSpec: AnimationSpec<Dp> = dpDefaultSpring,
+    finishedListener: ((Dp) -> Unit)? = null
+): State<Dp> = animateDpAsState(targetValue, animationSpec, finishedListener)
 
 /**
  * Fire-and-forget animation function for [Size]. This Composable function is overloaded for
@@ -168,14 +166,14 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateSizeAsState] returns a [State] object. The value of the state object will continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateSizeAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
- *     val size: Size by animateAsState(
+ *     val size: Size by animateSizeAsState(
  *         if (selected) Size(20f, 20f) else Size(10f, 10f))
  *
  * @param targetValue Target value of the animation
@@ -185,14 +183,12 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateSizeAsState(
     targetValue: Size,
-    animationSpec: AnimationSpec<Size> = remember {
-        spring(visibilityThreshold = Size.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<Size> = sizeDefaultSpring,
     finishedListener: ((Size) -> Unit)? = null
 ): State<Size> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue,
         Size.VectorConverter,
         animationSpec,
@@ -200,6 +196,22 @@
     )
 }
 
+private val sizeDefaultSpring = spring(visibilityThreshold = Size.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateSizeAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateSizeAsState"
+    )
+)
+@Composable
+fun animateAsState(
+    targetValue: Size,
+    animationSpec: AnimationSpec<Size> = sizeDefaultSpring,
+    finishedListener: ((Size) -> Unit)? = null
+): State<Size> = animateSizeAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * Fire-and-forget animation function for [Bounds]. This Composable function is overloaded for
  * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset],
@@ -207,14 +219,15 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateBoundsAsState] returns a [State] object. The value of the state object will
+ * continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateBoundsAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
- *    val bounds: Bounds by animateAsState(
+ *    val bounds: Bounds by animateBoundsAsState(
  *        if (collapsed) Bounds(0.dp, 0.dp, 10.dp, 20.dp) else Bounds(0.dp, 0.dp, 100.dp, 200.dp))
  *
  * @param targetValue Target value of the animation
@@ -224,14 +237,12 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateBoundsAsState(
     targetValue: Bounds,
-    animationSpec: AnimationSpec<Bounds> = remember {
-        spring(visibilityThreshold = Bounds.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<Bounds> = boundsDefaultSpring,
     finishedListener: ((Bounds) -> Unit)? = null
 ): State<Bounds> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue,
         Bounds.VectorConverter,
         animationSpec,
@@ -239,6 +250,22 @@
     )
 }
 
+private val boundsDefaultSpring = spring(visibilityThreshold = Bounds.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateBoundsAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateBoundsAsState"
+    )
+)
+@Composable
+fun animateAsState(
+    targetValue: Bounds,
+    animationSpec: AnimationSpec<Bounds> = boundsDefaultSpring,
+    finishedListener: ((Bounds) -> Unit)? = null
+): State<Bounds> = animateBoundsAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * Fire-and-forget animation function for [Offset]. This Composable function is overloaded for
  * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Float],
@@ -246,10 +273,10 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
- * updated by the animation until the animation finishes.
+ * [animateOffsetAsState] returns a [State] object. The value of the state object will
+ * continuously be updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateOffsetAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
@@ -262,18 +289,32 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateOffsetAsState(
     targetValue: Offset,
-    animationSpec: AnimationSpec<Offset> = remember {
-        spring(visibilityThreshold = Offset.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<Offset> = offsetDefaultSpring,
     finishedListener: ((Offset) -> Unit)? = null
 ): State<Offset> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue, Offset.VectorConverter, animationSpec, finishedListener = finishedListener
     )
 }
 
+private val offsetDefaultSpring = spring(visibilityThreshold = Offset.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateOffsetAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateOffsetAsState"
+    )
+)
+@Composable
+fun animateAsState(
+    targetValue: Offset,
+    animationSpec: AnimationSpec<Offset> = offsetDefaultSpring,
+    finishedListener: ((Offset) -> Unit)? = null
+): State<Offset> = animateOffsetAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * Fire-and-forget animation function for [Rect]. This Composable function is overloaded for
  * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset],
@@ -281,14 +322,14 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateRectAsState] returns a [State] object. The value of the state object will continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateRectAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
- *    val bounds: Rect by animateAsState(
+ *    val bounds: Rect by animateRectAsState(
  *        if (enabled) Rect(0f, 0f, 100f, 100f) else Rect(8f, 8f, 80f, 80f))
  *
  * @param targetValue Target value of the animation
@@ -298,18 +339,32 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateRectAsState(
     targetValue: Rect,
-    animationSpec: AnimationSpec<Rect> = remember {
-        spring(visibilityThreshold = Rect.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<Rect> = rectDefaultSpring,
     finishedListener: ((Rect) -> Unit)? = null
 ): State<Rect> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue, Rect.VectorConverter, animationSpec, finishedListener = finishedListener
     )
 }
 
+private val rectDefaultSpring = spring(visibilityThreshold = Rect.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateRectAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateRectAsState"
+    )
+)
+@Composable
+fun animateAsState(
+    targetValue: Rect,
+    animationSpec: AnimationSpec<Rect> = rectDefaultSpring,
+    finishedListener: ((Rect) -> Unit)? = null
+): State<Rect> = animateRectAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * Fire-and-forget animation function for [Int]. This Composable function is overloaded for
  * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset],
@@ -317,10 +372,10 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateIntAsState] returns a [State] object. The value of the state object will continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateIntAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
@@ -331,16 +386,32 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateIntAsState(
     targetValue: Int,
-    animationSpec: AnimationSpec<Int> = remember { spring(visibilityThreshold = 1) },
+    animationSpec: AnimationSpec<Int> = intDefaultSpring,
     finishedListener: ((Int) -> Unit)? = null
 ): State<Int> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue, Int.VectorConverter, animationSpec, finishedListener = finishedListener
     )
 }
 
+private val intDefaultSpring = spring(visibilityThreshold = Int.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateIntAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateIntAsState"
+    )
+)
+@Composable
+fun animateAsState(
+    targetValue: Int,
+    animationSpec: AnimationSpec<Int> = intDefaultSpring,
+    finishedListener: ((Int) -> Unit)? = null
+): State<Int> = animateIntAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * Fire-and-forget animation function for [IntOffset]. This Composable function is overloaded for
  * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset],
@@ -348,12 +419,12 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
- * updated by the animation until the animation finishes.
+ * [animateIntOffsetAsState] returns a [State] object. The value of the state object will
+ * continuously be updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
- * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
- * animations.
+ * Note, [animateIntOffsetAsState] cannot be canceled/stopped without removing this composable
+ * function from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for
+ * cancelable animations.
  *
  * @sample androidx.compose.animation.core.samples.AnimateOffsetSample
  *
@@ -364,18 +435,32 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateIntOffsetAsState(
     targetValue: IntOffset,
-    animationSpec: AnimationSpec<IntOffset> = remember {
-        spring(visibilityThreshold = IntOffset.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<IntOffset> = intOffsetDefaultSpring,
     finishedListener: ((IntOffset) -> Unit)? = null
 ): State<IntOffset> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue, IntOffset.VectorConverter, animationSpec, finishedListener = finishedListener
     )
 }
 
+private val intOffsetDefaultSpring = spring(visibilityThreshold = IntOffset.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateIntOffsetAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateIntOffsetAsState"
+    )
+)
+@Composable
+fun animateAsState(
+    targetValue: IntOffset,
+    animationSpec: AnimationSpec<IntOffset> = intOffsetDefaultSpring,
+    finishedListener: ((IntOffset) -> Unit)? = null
+): State<IntOffset> = animateIntOffsetAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * Fire-and-forget animation function for [IntSize]. This Composable function is overloaded for
  * different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset],
@@ -383,10 +468,10 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateIntSizeAsState] returns a [State] object. The value of the state object will continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateIntSizeAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
@@ -397,56 +482,31 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun animateAsState(
+fun animateIntSizeAsState(
     targetValue: IntSize,
-    animationSpec: AnimationSpec<IntSize> = remember {
-        spring(visibilityThreshold = IntSize.VisibilityThreshold)
-    },
+    animationSpec: AnimationSpec<IntSize> = intSizeDefaultSpring,
     finishedListener: ((IntSize) -> Unit)? = null
 ): State<IntSize> {
-    return animateAsState(
+    return animateValueAsState(
         targetValue, IntSize.VectorConverter, animationSpec, finishedListener = finishedListener
     )
 }
 
-/**
- * Fire-and-forget animation function for [AnimationVector]. This Composable function is overloaded
- * for different parameter types such as [Dp], [Color][androidx.compose.ui.graphics.Color], [Offset]
- * etc. When the provided [targetValue] is changed, the animation will run automatically. If there
- * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
- * course to animate towards the new target value.
- *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
- * updated by the animation until the animation finishes.
- *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
- * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
- * animations.
- *
- * @param targetValue Target value of the animation
- * @param animationSpec The animation that will be used to change the value through time. Physics
- *                    animation will be used by default.
- * @param visibilityThreshold An optional threshold to define when the animation value can be
- *                            considered close enough to the targetValue to end the animation.
- * @param finishedListener An optional end listener to get notified when the animation is finished.
- * @return A [State] object, the value of which is updated by animation.
- */
-@Composable
-fun <T : AnimationVector> animateAsState(
-    targetValue: T,
-    animationSpec: AnimationSpec<T> = remember {
-        spring(visibilityThreshold = visibilityThreshold)
-    },
-    visibilityThreshold: T? = null,
-    finishedListener: ((T) -> Unit)? = null
-): State<T> {
-    return animateAsState(
-        targetValue,
-        remember { TwoWayConverter<T, T>({ it }, { it }) },
-        animationSpec,
-        finishedListener = finishedListener
+private val intSizeDefaultSpring = spring(visibilityThreshold = IntSize.VisibilityThreshold)
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateIntSizeAsState(targetValue, animationSpec, finishedListener)",
+        "androidx.compose.animation.core.animateIntSizeAsState"
     )
-}
+)
+@Composable
+fun animateAsState(
+    targetValue: IntSize,
+    animationSpec: AnimationSpec<IntSize> = intSizeDefaultSpring,
+    finishedListener: ((IntSize) -> Unit)? = null
+): State<IntSize> = animateIntSizeAsState(targetValue, animationSpec, finishedListener)
 
 /**
  * Fire-and-forget animation function for any value. This Composable function is overloaded for
@@ -455,10 +515,10 @@
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
+ * [animateValueAsState] returns a [State] object. The value of the state object will continuously be
  * updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateValueAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedValue][androidx.compose.animation.animatedValue] for cancelable
  * animations.
  *
@@ -475,7 +535,7 @@
  * @return A [State] object, the value of which is updated by animation.
  */
 @Composable
-fun <T, V : AnimationVector> animateAsState(
+fun <T, V : AnimationVector> animateValueAsState(
     targetValue: T,
     typeConverter: TwoWayConverter<T, V>,
     animationSpec: AnimationSpec<T> = remember {
@@ -499,4 +559,25 @@
         listener?.invoke(animationState.value)
     }
     return animationState
-}
\ No newline at end of file
+}
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith(
+        "animateValueAsState(targetValue, typeConverter, animationSpec, visibilityThreshold, " +
+            "finishedListener)",
+        "androidx.compose.animation.core.animateValueAsState"
+    )
+)
+@Composable
+fun <T, V : AnimationVector> animateAsState(
+    targetValue: T,
+    typeConverter: TwoWayConverter<T, V>,
+    animationSpec: AnimationSpec<T> = remember {
+        spring(visibilityThreshold = visibilityThreshold)
+    },
+    visibilityThreshold: T? = null,
+    finishedListener: ((T) -> Unit)? = null
+): State<T> = animateValueAsState(
+    targetValue, typeConverter, animationSpec, visibilityThreshold, finishedListener
+)
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VisibilityThresholds.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VisibilityThresholds.kt
index 200c127..021d350 100644
--- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VisibilityThresholds.kt
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VisibilityThresholds.kt
@@ -114,3 +114,5 @@
  */
 val Bounds.Companion.VisibilityThreshold: Bounds
     get() = boundsVisibilityThreshold
+
+// TODO: Add Dp.DefaultAnimation = spring<Dp>(visibilityThreshold = Dp.VisibilityThreshold)
\ No newline at end of file
diff --git a/compose/animation/animation/api/current.txt b/compose/animation/animation/api/current.txt
index f2827a8..2c04394 100644
--- a/compose/animation/animation/api/current.txt
+++ b/compose/animation/animation/api/current.txt
@@ -139,16 +139,15 @@
     method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.ui.unit.Bounds animate(androidx.compose.ui.unit.Bounds target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.ui.geometry.Rect animate(androidx.compose.ui.geometry.Rect target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static int animate(int target, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? endListener);
-    method @Deprecated @androidx.compose.runtime.Composable public static <T extends androidx.compose.animation.core.AnimationVector> T animate(T target, optional androidx.compose.animation.core.AnimationSpec<T> animSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> T! animate(T? target, androidx.compose.animation.core.TwoWayConverter<T,V> converter, optional androidx.compose.animation.core.AnimationSpec<T> animSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-2AXSKHY(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? endListener);
-    method @Deprecated @androidx.compose.runtime.Composable public static long animate-4E4yWWY(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.DpOffset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.DpOffset,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-Cmzki-s(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static float animate-Lz7ev7o(float target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-m3E411Q(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-rlPqr8Y(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-t81mtYE(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? endListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateColorAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
   }
 
   public final class TransitionKt {
diff --git a/compose/animation/animation/api/public_plus_experimental_current.txt b/compose/animation/animation/api/public_plus_experimental_current.txt
index f2827a8..2c04394 100644
--- a/compose/animation/animation/api/public_plus_experimental_current.txt
+++ b/compose/animation/animation/api/public_plus_experimental_current.txt
@@ -139,16 +139,15 @@
     method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.ui.unit.Bounds animate(androidx.compose.ui.unit.Bounds target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.ui.geometry.Rect animate(androidx.compose.ui.geometry.Rect target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static int animate(int target, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? endListener);
-    method @Deprecated @androidx.compose.runtime.Composable public static <T extends androidx.compose.animation.core.AnimationVector> T animate(T target, optional androidx.compose.animation.core.AnimationSpec<T> animSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> T! animate(T? target, androidx.compose.animation.core.TwoWayConverter<T,V> converter, optional androidx.compose.animation.core.AnimationSpec<T> animSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-2AXSKHY(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? endListener);
-    method @Deprecated @androidx.compose.runtime.Composable public static long animate-4E4yWWY(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.DpOffset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.DpOffset,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-Cmzki-s(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static float animate-Lz7ev7o(float target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-m3E411Q(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-rlPqr8Y(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-t81mtYE(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? endListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateColorAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
   }
 
   public final class TransitionKt {
diff --git a/compose/animation/animation/api/restricted_current.txt b/compose/animation/animation/api/restricted_current.txt
index f2827a8..2c04394 100644
--- a/compose/animation/animation/api/restricted_current.txt
+++ b/compose/animation/animation/api/restricted_current.txt
@@ -139,16 +139,15 @@
     method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.ui.unit.Bounds animate(androidx.compose.ui.unit.Bounds target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Bounds> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Bounds,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.ui.geometry.Rect animate(androidx.compose.ui.geometry.Rect target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Rect,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static int animate(int target, optional androidx.compose.animation.core.AnimationSpec<java.lang.Integer> animSpec, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit>? endListener);
-    method @Deprecated @androidx.compose.runtime.Composable public static <T extends androidx.compose.animation.core.AnimationVector> T animate(T target, optional androidx.compose.animation.core.AnimationSpec<T> animSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static <T, V extends androidx.compose.animation.core.AnimationVector> T! animate(T? target, androidx.compose.animation.core.TwoWayConverter<T,V> converter, optional androidx.compose.animation.core.AnimationSpec<T> animSpec, optional T? visibilityThreshold, optional kotlin.jvm.functions.Function1<? super T,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-2AXSKHY(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntOffset,kotlin.Unit>? endListener);
-    method @Deprecated @androidx.compose.runtime.Composable public static long animate-4E4yWWY(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.DpOffset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.DpOffset,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-Cmzki-s(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.IntSize,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static float animate-Lz7ev7o(float target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Dp,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-m3E411Q(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-rlPqr8Y(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Size,kotlin.Unit>? endListener);
     method @Deprecated @androidx.compose.runtime.Composable public static long animate-t81mtYE(long target, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset> animSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit>? endListener);
-    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
+    method @Deprecated @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
+    method @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> animateColorAsState-m3E411Q(long targetValue, optional androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color> animationSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,kotlin.Unit>? finishedListener);
   }
 
   public final class TransitionKt {
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteAnimationDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteAnimationDemo.kt
index e0aa04d..689c1c3 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteAnimationDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteAnimationDemo.kt
@@ -52,7 +52,8 @@
     Box(Modifier.fillMaxSize()) {
         Icon(
             Icons.Filled.Favorite,
-            Modifier.align(Alignment.Center)
+            contentDescription = null,
+            modifier = Modifier.align(Alignment.Center)
                 .graphicsLayer(
                     scaleX = 3.0f,
                     scaleY = 3.0f,
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteTransitionDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteTransitionDemo.kt
index efc6be4..34e6bb1 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteTransitionDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/InfiniteTransitionDemo.kt
@@ -60,6 +60,7 @@
     Box(Modifier.fillMaxSize()) {
         Icon(
             Icons.Filled.Favorite,
+            null,
             Modifier.align(Alignment.Center)
                 .graphicsLayer(
                     scaleX = scale,
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/SingleValueAnimationDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/SingleValueAnimationDemo.kt
index 95ff665..bbcd355 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/SingleValueAnimationDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/SingleValueAnimationDemo.kt
@@ -18,7 +18,7 @@
 
 import androidx.compose.animation.Animatable
 import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.animation.core.spring
 import androidx.compose.foundation.InteractionState
 import androidx.compose.foundation.background
@@ -38,7 +38,7 @@
 @Composable
 fun SingleValueAnimationDemo() {
     val enabled = remember { mutableStateOf(true) }
-    val alpha: Float by animateAsState(if (enabled.value) 1f else 0.5f)
+    val alpha: Float by animateFloatAsState(if (enabled.value) 1f else 0.5f)
     val color = myAnimate(
         if (enabled.value) Color.Green else Color.Magenta,
         spring()
diff --git a/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedValueSamples.kt b/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedValueSamples.kt
index 6f506e3..474b404 100644
--- a/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedValueSamples.kt
+++ b/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedValueSamples.kt
@@ -19,7 +19,7 @@
 import androidx.annotation.Sampled
 import androidx.compose.animation.Animatable
 import androidx.compose.animation.animate
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.AnimationVector2D
 import androidx.compose.animation.core.TwoWayConverter
@@ -126,7 +126,7 @@
         // Animates to primary or secondary color, depending on whether [primary] is true
         // [animateState] returns the current animation value in a State<Color> in this example. We
         // use the State<Color> object as a property delegate here.
-        val color: Color by animateAsState(
+        val color: Color by animateColorAsState(
             if (primary) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
         )
         Box(modifier = Modifier.background(color))
diff --git a/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedVisibilitySamples.kt b/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedVisibilitySamples.kt
index 7ed33cb..959558b 100644
--- a/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedVisibilitySamples.kt
+++ b/compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedVisibilitySamples.kt
@@ -170,7 +170,11 @@
         modifier = with(ColumnScope) { Modifier.align(Alignment.CenterHorizontally) }
     ) {
         Row(Modifier.padding(start = 12.dp, end = 12.dp)) {
-            Icon(Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically))
+            Icon(
+                Icons.Default.Favorite,
+                contentDescription = "Favorite",
+                modifier = Modifier.align(Alignment.CenterVertically)
+            )
             AnimatedVisibility(
                 expanded,
                 modifier = Modifier.align(Alignment.CenterVertically)
diff --git a/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SingleValueAnimation.kt b/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SingleValueAnimation.kt
index 5de481d..5fb5489 100644
--- a/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SingleValueAnimation.kt
+++ b/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SingleValueAnimation.kt
@@ -29,7 +29,7 @@
 import androidx.compose.animation.core.TwoWayConverter
 import androidx.compose.animation.core.VectorConverter
 import androidx.compose.animation.core.VisibilityThreshold
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateValueAsState
 import androidx.compose.animation.core.animateDecay
 import androidx.compose.animation.core.animateTo
 import androidx.compose.animation.core.isFinished
@@ -50,10 +50,8 @@
 import androidx.compose.ui.platform.AmbientAnimationClock
 import androidx.compose.ui.unit.Bounds
 import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpOffset
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.Position
 
 private val defaultAnimation = spring<Float>()
 
@@ -75,10 +73,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateFloatAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, visibilityThreshold, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateFloatAsState(target, animSpec, visibilityThreshold, endListener).value",
+        "androidx.compose.animation.core.animateFloatAsState"
     )
 )
 @Composable
@@ -127,16 +125,16 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateColorAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.animateAsState"
+        "animateColorAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.animateColorAsState"
     )
 )
 @Composable
 fun animate(
     target: Color,
-    animSpec: AnimationSpec<Color> = remember { spring() },
+    animSpec: AnimationSpec<Color> = colorDefaultSpring,
     endListener: ((Color) -> Unit)? = null
 ): Color {
     val converter = remember(target.colorSpace) { (Color.VectorConverter)(target.colorSpace) }
@@ -159,10 +157,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateDpAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateDpAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateDpAsState"
     )
 )
 @Composable
@@ -177,42 +175,6 @@
 }
 
 /**
- * Fire-and-forget animation [Composable] for [Position]. Once such an animation is created, it will
- * be positionally memoized, like other @[Composable]s. To trigger the animation, or alter the
- * course of the animation, simply supply a different [target] to the [Composable].
- *
- * Note, [animateTo] is for simple animations that cannot be canceled. For cancellable animations
- * see [animatedValue].
- *
- *     val position : Position = animate(
- *         if (selected) Position(0.dp, 0.dp) else Position(20.dp, 20.dp))
- *
- * @param target Target value of the animation
- * @param animSpec The animation that will be used to change the value through time. Physics
- *                    animation will be used by default.
- * @param endListener An optional end listener to get notified when the animation is finished.
- */
-@Deprecated(
-    "animate has been replaced with animateAsState",
-    ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
-    )
-)
-@Composable
-fun animate(
-    target: Position,
-    animSpec: AnimationSpec<Position> = remember {
-        spring(visibilityThreshold = Position.VisibilityThreshold)
-    },
-    endListener: ((Position) -> Unit)? = null
-): Position {
-    return animate(
-        target, Position.VectorConverter, animSpec, endListener = endListener
-    )
-}
-
-/**
  * Fire-and-forget animation [Composable] for [Size]. Once such an animation is created, it will be
  * positionally memoized, like other @[Composable]s. To trigger the animation, or alter the
  * course of the animation, simply supply a different [target] to the [Composable].
@@ -229,10 +191,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateSizeAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateSizeAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateSizeAsState"
     )
 )
 @Composable
@@ -263,10 +225,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateBoundsAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateBoundsAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateBoundsAsState"
     )
 )
 @Composable
@@ -301,10 +263,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateOffsetAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateOffsetAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateOffsetAsState"
     )
 )
 @Composable
@@ -337,10 +299,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateRectAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateRectAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateRectAsState"
     )
 )
 @Composable
@@ -370,10 +332,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateIntAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateIntAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateIntAsState"
     )
 )
 @Composable
@@ -403,10 +365,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateIntOffsetAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateIntOffsetAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateIntOffsetAsState"
     )
 )
 @Composable
@@ -436,10 +398,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateIntSizeAsState",
     ReplaceWith(
-        "animateAsState(target, animSpec, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateIntSizeAsState(target, animSpec, endListener).value",
+        "androidx.compose.animation.core.animateIntSizeAsState"
     )
 )
 @Composable
@@ -456,45 +418,6 @@
 }
 
 /**
- * Fire-and-forget animation [Composable] for [AnimationVector]. Once such an animation is created,
- * it will be positionally memoized, like other @[Composable]s. To trigger the animation, or alter
- * the course of the animation, simply supply a different [target] to the [Composable].
- *
- * Note, [animateTo] is for simple animations that cannot be canceled. For cancellable animations
- * see [animatedValue].
- *
- * @param target Target value of the animation
- * @param animSpec The animation that will be used to change the value through time. Physics
- *                    animation will be used by default.
- * @param visibilityThreshold An optional threshold to define when the animation value can be
- *                            considered close enough to the target to end the animation.
- * @param endListener An optional end listener to get notified when the animation is finished.
- */
-@Deprecated(
-    "animate has been replaced with animateAsState",
-    ReplaceWith(
-        "animateAsState(target, animSpec, visibilityThreshold, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
-    )
-)
-@Composable
-fun <T : AnimationVector> animate(
-    target: T,
-    animSpec: AnimationSpec<T> = remember {
-        spring(visibilityThreshold = visibilityThreshold)
-    },
-    visibilityThreshold: T? = null,
-    endListener: ((T) -> Unit)? = null
-): T {
-    return animate(
-        target,
-        remember { TwoWayConverter<T, T>({ it }, { it }) },
-        animSpec,
-        endListener = endListener
-    )
-}
-
-/**
  * Fire-and-forget animation [Composable] for any value. Once such an animation is created, it
  * will be positionally memoized, like other @[Composable]s. To trigger the animation, or alter
  * the course of the animation, simply supply a different [target] to the [Composable].
@@ -514,10 +437,10 @@
  * @param endListener An optional end listener to get notified when the animation is finished.
  */
 @Deprecated(
-    "animate has been replaced with animateAsState",
+    "animate has been replaced with animateValueAsState",
     ReplaceWith(
-        "animateAsState(target, converter, animSpec, visibilityThreshold, endListener).value",
-        "androidx.compose.animation.core.animateAsState"
+        "animateValueAsState(target, converter, animSpec, visibilityThreshold, endListener).value",
+        "androidx.compose.animation.core.animateValueAsState"
     )
 )
 @Composable
@@ -551,15 +474,15 @@
 
 /**
  * Fire-and-forget animation function for [Color]. This Composable function is overloaded for
- * different parameter types such as [Dp], [Float], [Int], [Size], [Offset], [DpOffset],
+ * different parameter types such as [Dp], [Float], [Int], [Size], [Offset],
  * etc. When the provided [targetValue] is changed, the animation will run automatically. If there
  * is already an animation in-flight whe [targetValue] changes, the on-going animation will adjust
  * course to animate towards the new target value.
  *
- * [animateAsState] returns a [State] object. The value of the state object will continuously be
- * updated by the animation until the animation finishes.
+ * [animateColorAsState] returns a [State] object. The value of the state object will
+ * continuously be updated by the animation until the animation finishes.
  *
- * Note, [animateAsState] cannot be canceled/stopped without removing this composable function
+ * Note, [animateColorAsState] cannot be canceled/stopped without removing this composable function
  * from the tree. See [animatedColor][androidx.compose.animation.animatedColor] for cancelable
  * animations.
  *
@@ -571,19 +494,32 @@
  * @param finishedListener An optional end listener to get notified when the animation is finished.
  */
 @Composable
-fun animateAsState(
+fun animateColorAsState(
     targetValue: Color,
-    animationSpec: AnimationSpec<Color> = remember { spring() },
+    animationSpec: AnimationSpec<Color> = colorDefaultSpring,
     finishedListener: ((Color) -> Unit)? = null
 ): State<Color> {
     val converter = remember(targetValue.colorSpace) {
         (Color.VectorConverter)(targetValue.colorSpace)
     }
-    return animateAsState(
+    return animateValueAsState(
         targetValue, converter, animationSpec, finishedListener = finishedListener
     )
 }
 
+private val colorDefaultSpring = spring<Color>()
+
+@Deprecated(
+    "animateAsState has been yet again renamed",
+    ReplaceWith("animateColorAsState(targetValue, animationSpec, finishedListener)")
+)
+@Composable
+fun animateAsState(
+    targetValue: Color,
+    animationSpec: AnimationSpec<Color> = colorDefaultSpring,
+    finishedListener: ((Color) -> Unit)? = null
+): State<Color> = animateColorAsState(targetValue, animationSpec, finishedListener)
+
 /**
  * This [Animatable] function creates a Color value holder that automatically
  * animates its value when the value is changed via [animateTo]. [Animatable] supports value
diff --git a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt
index 1bcfea1..a56eef7 100644
--- a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt
+++ b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/example1/Main.kt
@@ -15,7 +15,7 @@
  */
 package androidx.compose.desktop.examples.example1
 
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.animation.core.TweenSpec
 import androidx.compose.desktop.AppWindow
 import androidx.compose.desktop.DesktopMaterialTheme
@@ -117,7 +117,7 @@
                 TopAppBar(
                     title = {
                         Row(verticalAlignment = Alignment.CenterVertically) {
-                            Icon(Icons.Outlined.Home)
+                            Icon(Icons.Outlined.Home, "Home")
                             Text(title)
                         }
                     }
@@ -137,7 +137,7 @@
                     IconButton(
                         >
                     ) {
-                        Icon(Icons.Filled.Menu, Modifier.size(ButtonDefaults.IconSize))
+                        Icon(Icons.Filled.Menu, "Menu", Modifier.size(ButtonDefaults.IconSize))
                     }
                 }
             },
@@ -397,11 +397,13 @@
         Row {
             Image(
                 imageResource("androidx/compose/desktop/example/circus.jpg"),
+                "Localized description",
                 Modifier.size(200.dp)
             )
 
             Icon(
                 vectorXmlResource("androidx/compose/desktop/example/ic_baseline_deck_24.xml"),
+                "Localized description",
                 Modifier.size(100.dp).align(Alignment.CenterVertically),
                 tint = Color.Blue.copy(alpha = 0.5f)
             )
@@ -416,7 +418,7 @@
     }
 
     val enabled = remember { mutableStateOf(true) }
-    val color by animateAsState(
+    val color by animateColorAsState(
         if (enabled.value) Color.Green else Color.Red,
         animationSpec = TweenSpec(durationMillis = 2000)
     )
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
index 7a1d75e..256536c 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
@@ -45,11 +45,12 @@
         /**
          * Horizontally places the layout children.
          *
-         * @param totalSize Available space that can be occupied by the children.
-         * @param sizes An array of sizes of all children.
+         * @param totalSize Available space that can be occupied by the children, in pixels.
+         * @param sizes An array of sizes of all children, in pixels.
          * @param layoutDirection A layout direction, left-to-right or right-to-left, of the parent
          * layout that should be taken into account when determining positions of the children.
-         * @param outPositions An array of the size of [sizes] that returns the calculated positions.
+         * @param outPositions An array of the size of [sizes] that returns the calculated
+         * positions relative to the left, in pixels.
          */
         fun Density.arrange(
             totalSize: Int,
@@ -72,9 +73,10 @@
         /**
          * Vertically places the layout children.
          *
-         * @param totalSize Available space that can be occupied by the children.
-         * @param sizes An array of sizes of all children.
-         * @param outPositions An array of the size of [sizes] that returns the calculated positions.
+         * @param totalSize Available space that can be occupied by the children, in pixels.
+         * @param sizes An array of sizes of all children, in pixels.
+         * @param outPositions An array of the size of [sizes] that returns the calculated
+         * positions relative to the top, in pixels.
          */
         fun Density.arrange(
             totalSize: Int,
@@ -98,7 +100,8 @@
 
     /**
      * Place children horizontally such that they are as close as possible to the beginning of the
-     * main axis.
+     * horizontal axis (left if the layout direction is LTR, right otherwise).
+     * Visually: 123#### for LTR and ####321.
      */
     @Stable
     val Start = object : Horizontal {
@@ -114,11 +117,14 @@
             placeRightOrBottom(totalSize, sizes, outPositions)
             outPositions.reverse()
         }
+
+        override fun toString() = "Arrangement#Start"
     }
 
     /**
      * Place children horizontally such that they are as close as possible to the end of the main
      * axis.
+     * Visually: ####123 for LTR and 321#### for RTL.
      */
     @Stable
     val End = object : Horizontal {
@@ -134,11 +140,14 @@
             placeLeftOrTop(sizes, outPositions)
             outPositions.reverse()
         }
+
+        override fun toString() = "Arrangement#End"
     }
 
     /**
      * Place children vertically such that they are as close as possible to the top of the main
      * axis.
+     * Visually: (top) 123#### (bottom)
      */
     @Stable
     val Top = object : Vertical {
@@ -147,11 +156,14 @@
             sizes: IntArray,
             outPositions: IntArray
         ) = placeLeftOrTop(sizes, outPositions)
+
+        override fun toString() = "Arrangement#Top"
     }
 
     /**
      * Place children vertically such that they are as close as possible to the bottom of the main
      * axis.
+     * Visually: (top) ####123 (bottom)
      */
     @Stable
     val Bottom = object : Vertical {
@@ -160,10 +172,13 @@
             sizes: IntArray,
             outPositions: IntArray
         ) = placeRightOrBottom(totalSize, sizes, outPositions)
+
+        override fun toString() = "Arrangement#Start"
     }
 
     /**
      * Place children such that they are as close as possible to the middle of the main axis.
+     * Visually: ##123## for LTR and ##321## for RTL.
      */
     @Stable
     val Center = object : HorizontalOrVertical {
@@ -187,11 +202,14 @@
             sizes: IntArray,
             outPositions: IntArray
         ) = placeCenter(totalSize, sizes, outPositions)
+
+        override fun toString() = "Arrangement#Center"
     }
 
     /**
      * Place children such that they are spaced evenly across the main axis, including free
      * space before the first child and after the last child.
+     * Visually: #1#2#3# for LTR and #3#2#1# for RTL.
      */
     @Stable
     val SpaceEvenly = object : HorizontalOrVertical {
@@ -215,11 +233,14 @@
             sizes: IntArray,
             outPositions: IntArray
         ) = placeSpaceEvenly(totalSize, sizes, outPositions)
+
+        override fun toString() = "Arrangement#SpaceEvenly"
     }
 
     /**
      * Place children such that they are spaced evenly across the main axis, without free
      * space before the first child or after the last child.
+     * Visually: 1##2##3 for LTR or 3##2##1 for RTL.
      */
     @Stable
     val SpaceBetween = object : HorizontalOrVertical {
@@ -243,12 +264,15 @@
             sizes: IntArray,
             outPositions: IntArray
         ) = placeSpaceBetween(totalSize, sizes, outPositions)
+
+        override fun toString() = "Arrangement#SpaceBetween"
     }
 
     /**
      * Place children such that they are spaced evenly across the main axis, including free
      * space before the first child and after the last child, but half the amount of space
      * existing otherwise between two consecutive children.
+     * Visually: #1##2##3# for LTR and #3##2##1# for RTL
      */
     @Stable
     val SpaceAround = object : HorizontalOrVertical {
@@ -272,6 +296,8 @@
             sizes: IntArray,
             outPositions: IntArray
         ) = placeSpaceAround(totalSize, sizes, outPositions)
+
+        override fun toString() = "Arrangement#SpaceAround"
     }
 
     /**
@@ -345,6 +371,8 @@
          *
          * Unlike [Arrangement.Start], when the layout direction is RTL, the children will not be
          * mirrored and as such children will appear in the order they are composed inside the [Row].
+         *
+         * Visually: 123####
          */
         @Stable
         val Left = object : Horizontal {
@@ -354,6 +382,8 @@
                 layoutDirection: LayoutDirection,
                 outPositions: IntArray
             ) = placeLeftOrTop(sizes, outPositions)
+
+            override fun toString() = "AbsoluteArrangement#Left"
         }
 
         /**
@@ -361,6 +391,8 @@
          *
          * Unlike [Arrangement.Center], when the layout direction is RTL, the children will not be
          * mirrored and as such children will appear in the order they are composed inside the [Row].
+         *
+         * Visually: ##123##
          */
         @Stable
         val Center = object : Horizontal {
@@ -370,6 +402,8 @@
                 layoutDirection: LayoutDirection,
                 outPositions: IntArray
             ) = placeCenter(totalSize, sizes, outPositions)
+
+            override fun toString() = "AbsoluteArrangement#Center"
         }
 
         /**
@@ -378,6 +412,8 @@
          *
          * Unlike [Arrangement.End], when the layout direction is RTL, the children will not be
          * mirrored and as such children will appear in the order they are composed inside the [Row].
+         *
+         * Visually: ####123
          */
         @Stable
         val Right = object : Horizontal {
@@ -387,6 +423,8 @@
                 layoutDirection: LayoutDirection,
                 outPositions: IntArray
             ) = placeRightOrBottom(totalSize, sizes, outPositions)
+
+            override fun toString() = "AbsoluteArrangement#Right"
         }
 
         /**
@@ -395,6 +433,8 @@
          *
          * Unlike [Arrangement.SpaceBetween], when the layout direction is RTL, the children will not be
          * mirrored and as such children will appear in the order they are composed inside the [Row].
+         *
+         * Visually: 1##2##3
          */
         @Stable
         val SpaceBetween = object : Horizontal {
@@ -404,6 +444,8 @@
                 layoutDirection: LayoutDirection,
                 outPositions: IntArray
             ) = placeSpaceBetween(totalSize, sizes, outPositions)
+
+            override fun toString() = "AbsoluteArrangement#SpaceBetween"
         }
 
         /**
@@ -412,6 +454,8 @@
          *
          * Unlike [Arrangement.SpaceEvenly], when the layout direction is RTL, the children will not be
          * mirrored and as such children will appear in the order they are composed inside the [Row].
+         *
+         * Visually: #1#2#3#
          */
         @Stable
         val SpaceEvenly = object : Horizontal {
@@ -421,6 +465,8 @@
                 layoutDirection: LayoutDirection,
                 outPositions: IntArray
             ) = placeSpaceEvenly(totalSize, sizes, outPositions)
+
+            override fun toString() = "AbsoluteArrangement#SpaceEvenly"
         }
 
         /**
@@ -430,6 +476,8 @@
          *
          * Unlike [Arrangement.SpaceAround], when the layout direction is RTL, the children will not be
          * mirrored and as such children will appear in the order they are composed inside the [Row].
+         *
+         * Visually: #1##2##3##4#
          */
         @Stable
         val SpaceAround = object : Horizontal {
@@ -439,6 +487,8 @@
                 layoutDirection: LayoutDirection,
                 outPositions: IntArray
             ) = placeSpaceAround(totalSize, sizes, outPositions)
+
+            override fun toString() = "AbsoluteArrangement#SpaceAround"
         }
 
         /**
@@ -546,11 +596,15 @@
 
             if (layoutDirection == LayoutDirection.Rtl && rtlMirror) outPositions.reverse()
         }
+
         override fun Density.arrange(
             totalSize: Int,
             sizes: IntArray,
             outPositions: IntArray
         ) = arrange(totalSize, sizes, LayoutDirection.Ltr, outPositions)
+
+        override fun toString() =
+            "${if (rtlMirror) "" else "Absolute"}Arrangement#spacedAligned($space, $alignment)"
     }
 
     internal fun placeRightOrBottom(
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
index 78f6cec..7a161de 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Padding.kt
@@ -40,7 +40,7 @@
  * Padding is applied before content measurement and takes precedence; content may only be as large
  * as the remaining space.
  *
- * Negative padding is not permitted. See [offset].
+ * Negative padding is not permitted. See [Modifier.offset].
  *
  * Example usage:
  * @sample androidx.compose.foundation.layout.samples.PaddingModifier
@@ -74,7 +74,7 @@
  * Padding is applied before content measurement and takes precedence; content may only be as large
  * as the remaining space.
  *
- * Negative padding is not permitted. See [offset].
+ * Negative padding is not permitted. See [Modifier.offset].
  *
  * Example usage:
  * @sample androidx.compose.foundation.layout.samples.SymmetricPaddingModifier
@@ -103,7 +103,7 @@
  * Padding is applied before content measurement and takes precedence; content may only be as large
  * as the remaining space.
  *
- * Negative padding is not permitted. See [offset].
+ * Negative padding is not permitted. See [Modifier.offset].
  *
  * Example usage:
  * @sample androidx.compose.foundation.layout.samples.PaddingAllModifier
@@ -129,7 +129,7 @@
  * top, right and bottom. Padding is applied before content measurement and takes precedence;
  * content may only be as large as the remaining space.
  *
- * Negative padding is not permitted. See [offset].
+ * Negative padding is not permitted. See [Modifier.offset].
  *
  * Example usage:
  * @sample androidx.compose.foundation.layout.samples.PaddingValuesModifier
@@ -158,7 +158,7 @@
  * [padding] to apply relative paddings. Padding is applied before content measurement and takes
  * precedence; content may only be as large as the remaining space.
  *
- * Negative padding is not permitted. See [offset].
+ * Negative padding is not permitted. See [Modifier.offset].
  *
  * Example usage:
  * @sample androidx.compose.foundation.layout.samples.AbsolutePaddingModifier
@@ -258,5 +258,14 @@
     @Stable
     val bottom: Dp = 0.dp
 ) {
+    /**
+     * Describes a padding of [all] dp along all 4 edges.
+     */
     constructor(all: Dp) : this(all, all, all, all)
+
+    /**
+     * Describes a padding of [horizontal] dp along the left and right edges, and of [vertical]
+     * dp along the top and bottom edges.
+     */
+    constructor(horizontal: Dp, vertical: Dp) : this(horizontal, vertical, horizontal, vertical)
 }
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index b0c049a..e2ea5c1 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -66,9 +66,9 @@
   }
 
   public final class ImageKt {
-    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.ImageBitmap bitmap, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
-    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.vector.ImageVector imageVector, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
-    method @androidx.compose.runtime.Composable public static void Image(androidx.compose.ui.graphics.painter.Painter painter, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static void Image(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
   }
 
   @androidx.compose.runtime.Stable public interface Indication {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index b0c049a..e2ea5c1 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -66,9 +66,9 @@
   }
 
   public final class ImageKt {
-    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.ImageBitmap bitmap, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
-    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.vector.ImageVector imageVector, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
-    method @androidx.compose.runtime.Composable public static void Image(androidx.compose.ui.graphics.painter.Painter painter, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static void Image(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
   }
 
   @androidx.compose.runtime.Stable public interface Indication {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index b0c049a..e2ea5c1 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -66,9 +66,9 @@
   }
 
   public final class ImageKt {
-    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.ImageBitmap bitmap, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
-    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.vector.ImageVector imageVector, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
-    method @androidx.compose.runtime.Composable public static void Image(androidx.compose.ui.graphics.painter.Painter painter, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static inline void Image(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
+    method @androidx.compose.runtime.Composable public static void Image(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.Alignment alignment, optional androidx.compose.ui.layout.ContentScale contentScale, optional float alpha, optional androidx.compose.ui.graphics.ColorFilter? colorFilter);
   }
 
   @androidx.compose.runtime.Stable public interface Indication {
diff --git a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/BasicTextFieldSamples.kt b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/BasicTextFieldSamples.kt
index db44c17..d1cc274 100644
--- a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/BasicTextFieldSamples.kt
+++ b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/BasicTextFieldSamples.kt
@@ -101,7 +101,7 @@
                     .background(Color.LightGray, RoundedCornerShape(percent = 30))
                     .padding(16.dp)
             ) {
-                Icon(Icons.Default.MailOutline)
+                Icon(Icons.Default.MailOutline, contentDescription = null)
                 Spacer(Modifier.width(16.dp))
                 innerTextField()
             }
diff --git a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt
index 904f536..fd4f49f 100644
--- a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt
+++ b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/ImageSamples.kt
@@ -43,7 +43,7 @@
 fun ImageSample() {
     val ImageBitmap = createTestImage()
     // Lays out and draws an image sized to the dimensions of the ImageBitmap
-    Image(bitmap = ImageBitmap)
+    Image(bitmap = ImageBitmap, contentDescription = "Localized description")
 }
 
 @Sampled
@@ -56,7 +56,8 @@
             ImageBitmap,
             IntOffset(10, 12),
             IntSize(50, 60)
-        )
+        ),
+        contentDescription = "Localized description"
     )
 }
 
@@ -67,6 +68,7 @@
     imageVector.resource.resource?.let {
         Image(
             imageVector = it,
+            contentDescription = null,
             modifier = Modifier.preferredSize(200.dp, 200.dp),
             contentScale = ContentScale.Fit,
             colorFilter = ColorFilter.tint(Color.Cyan)
@@ -89,7 +91,11 @@
         }
     }
 
-    Image(painter = customPainter, modifier = Modifier.preferredSize(100.dp, 100.dp))
+    Image(
+        painter = customPainter,
+        contentDescription = "Localized description",
+        modifier = Modifier.preferredSize(100.dp, 100.dp)
+    )
 }
 
 /**
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt
index b49f36d..1e6f611 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ImageTest.kt
@@ -56,6 +56,7 @@
 import androidx.compose.ui.platform.AmbientDensity
 import androidx.compose.ui.res.imageResource
 import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -113,7 +114,11 @@
                     .background(color = Color.White)
                     .wrapContentSize(Alignment.Center)
             ) {
-                Image(modifier = Modifier.testTag(contentTag), bitmap = createImageBitmap())
+                Image(
+                    modifier = Modifier.testTag(contentTag),
+                    contentDescription = null,
+                    bitmap = createImageBitmap()
+                )
             }
         }
 
@@ -162,7 +167,8 @@
                             imageHeight / 2 - subsectionHeight / 2
                         ),
                         IntSize(subsectionWidth, subsectionHeight)
-                    )
+                    ),
+                    null
                 )
             }
         }
@@ -258,6 +264,7 @@
                 // the bounds
                 Image(
                     bitmap = createImageBitmap(),
+                    contentDescription = null,
                     modifier = Modifier
                         .testTag(contentTag)
                         .preferredSize(
@@ -325,6 +332,7 @@
             ) {
                 Image(
                     bitmap = ImageBitmap,
+                    contentDescription = null,
                     modifier = Modifier
                         .testTag(contentTag)
                         .preferredSize(
@@ -357,6 +365,7 @@
                 // ImageBitmap that is to be drawn in the bottom end section of the composable
                 Image(
                     bitmap = createImageBitmap(),
+                    contentDescription = null,
                     modifier = Modifier
                         .testTag(contentTag)
                         .preferredSize(
@@ -420,6 +429,7 @@
                 loadVectorResource(R.drawable.ic_vector_asset_test).resource.resource?.let {
                     Image(
                         it,
+                        null,
                         modifier = Modifier.preferredSizeIn(
                             minWidth = minWidth,
                             minHeight = minHeight
@@ -505,6 +515,7 @@
             val heightDp = asset.height / AmbientDensity.current.density
             Image(
                 asset,
+                null,
                 modifier = Modifier
                     .testTag(testTag)
                     .background(Color.Green)
@@ -540,14 +551,15 @@
             }
             Image(
                 painterResource(painterId.value),
-                contentScale = ContentScale.FillBounds,
+                null,
                 modifier = Modifier.testTag(testTag).clickable {
                     if (painterId.value == R.drawable.ic_vector_square_asset_test) {
                         painterId.value = R.drawable.ic_image_test
                     } else {
                         painterId.value = R.drawable.ic_vector_square_asset_test
                     }
-                }
+                },
+                contentScale = ContentScale.FillBounds
             )
         }
 
@@ -559,4 +571,20 @@
 
         rule.onNodeWithTag(testTag).captureToImage().assertPixels { imageColor }
     }
+
+    @Test
+    fun testImageContentDescription() {
+        val testTag = "TestTag"
+        rule.setContent {
+            Image(
+                bitmap = ImageBitmap(100, 100),
+                modifier = Modifier.testTag(testTag),
+                contentDescription = "asdf"
+            )
+        }
+        rule.onNodeWithTag(testTag).fetchSemanticsNode().let {
+            Assert.assertTrue(it.config.contains(SemanticsProperties.ContentDescription))
+            Assert.assertEquals(it.config[SemanticsProperties.ContentDescription], "asdf")
+        }
+    }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt
index 32e24c0..72f9598 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Image.kt
@@ -33,6 +33,8 @@
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.graphics.vector.rememberVectorPainter
 import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
 
 /**
  * A composable that lays out and draws a given [ImageBitmap]. This will attempt to
@@ -49,13 +51,17 @@
  * overload that consumes a [Painter] parameter shown in this sample
  * @sample androidx.compose.foundation.samples.ImagePainterSubsectionSample
  *
- * @param bitmap The [ImageBitmap] to draw.
+ * @param bitmap The [ImageBitmap] to draw
+ * @param contentDescription text used by accessibility services to describe what this image
+ * represents. This should always be provided unless this image is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
  * background)
  * @param alignment Optional alignment parameter used to place the [ImageBitmap] in the given
- * bounds defined by the width and height.
+ * bounds defined by the width and height
  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be used
- * if the bounds are a different size from the intrinsic size of the [ImageBitmap].
+ * if the bounds are a different size from the intrinsic size of the [ImageBitmap]
  * @param alpha Optional opacity to be applied to the [ImageBitmap] when it is rendered onscreen
  * @param colorFilter Optional ColorFilter to apply for the [ImageBitmap] when it is rendered
  * onscreen
@@ -64,6 +70,7 @@
 @Composable
 inline fun Image(
     bitmap: ImageBitmap,
+    contentDescription: String?,
     modifier: Modifier = Modifier,
     alignment: Alignment = Alignment.Center,
     contentScale: ContentScale = ContentScale.Fit,
@@ -73,6 +80,7 @@
     val imagePainter = remember(bitmap) { ImagePainter(bitmap) }
     Image(
         painter = imagePainter,
+        contentDescription = contentDescription,
         modifier = modifier,
         alignment = alignment,
         contentScale = contentScale,
@@ -90,13 +98,17 @@
  *
  * @sample androidx.compose.foundation.samples.ImageVectorSample
  *
- * @param imageVector The [ImageVector] to draw.
+ * @param imageVector The [ImageVector] to draw
+ * @param contentDescription text used by accessibility services to describe what this image
+ * represents. This should always be provided unless this image is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
  * background)
  * @param alignment Optional alignment parameter used to place the [ImageVector] in the given
- * bounds defined by the width and height.
+ * bounds defined by the width and height
  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be used
- * if the bounds are a different size from the intrinsic size of the [ImageVector].
+ * if the bounds are a different size from the intrinsic size of the [ImageVector]
  * @param alpha Optional opacity to be applied to the [ImageVector] when it is rendered onscreen
  * @param colorFilter Optional ColorFilter to apply for the [ImageVector] when it is rendered
  * onscreen
@@ -105,6 +117,7 @@
 @Composable
 inline fun Image(
     imageVector: ImageVector,
+    contentDescription: String?,
     modifier: Modifier = Modifier,
     alignment: Alignment = Alignment.Center,
     contentScale: ContentScale = ContentScale.Fit,
@@ -112,6 +125,7 @@
     colorFilter: ColorFilter? = null
 ) = Image(
     painter = rememberVectorPainter(imageVector),
+    contentDescription = contentDescription,
     modifier = modifier,
     alignment = alignment,
     contentScale = contentScale,
@@ -132,12 +146,16 @@
  * @sample androidx.compose.foundation.samples.ImagePainterSample
  *
  * @param painter to draw
+ * @param contentDescription text used by accessibility services to describe what this image
+ * represents. This should always be provided unless this image is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
  * background)
  * @param alignment Optional alignment parameter used to place the [Painter] in the given
  * bounds defined by the width and height.
  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be used
- * if the bounds are a different size from the intrinsic size of the [Painter].
+ * if the bounds are a different size from the intrinsic size of the [Painter]
  * @param alpha Optional opacity to be applied to the [Painter] when it is rendered onscreen
  * the default renders the [Painter] completely opaque
  * @param colorFilter Optional colorFilter to apply for the [Painter] when it is rendered onscreen
@@ -145,17 +163,24 @@
 @Composable
 fun Image(
     painter: Painter,
+    contentDescription: String?,
     modifier: Modifier = Modifier,
     alignment: Alignment = Alignment.Center,
     contentScale: ContentScale = ContentScale.Fit,
     alpha: Float = DefaultAlpha,
     colorFilter: ColorFilter? = null
 ) {
+    val semantics = if (contentDescription != null) {
+        Modifier.semantics { this.contentDescription = contentDescription }
+    } else {
+        Modifier
+    }
+
     // Explicitly use a simple Layout implementation here as Spacer squashes any non fixed
     // constraint with zero
     Layout(
         emptyContent(),
-        modifier.clipToBounds().paint(
+        modifier.then(semantics).clipToBounds().paint(
             painter,
             alignment = alignment,
             contentScale = contentScale,
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
index 9e063c6..0cb8885 100644
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/Scrollbar.kt
@@ -16,7 +16,7 @@
 
 package androidx.compose.foundation
 
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.animation.core.TweenSpec
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.lazy.LazyListState
@@ -217,7 +217,7 @@
         }
     }
 
-    val color by animateAsState(
+    val color by animateColorAsState(
         if (isHover) style.hoverColor else style.unhoverColor,
         animationSpec = TweenSpec(durationMillis = style.hoverDurationMillis)
     )
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
index 3c14b88..f84c765 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
@@ -182,21 +182,21 @@
             LayoutDirection.Rtl -> Icons.Filled.ArrowForward
         }
         IconButton( {
-            Icon(icon)
+            Icon(icon, null)
         }
     }
 
     @Composable
     fun Filter(onClick: () -> Unit) {
         IconButton(modifier = Modifier.testTag(Tags.FilterButton),  {
-            Icon(Icons.Filled.Search)
+            Icon(Icons.Filled.Search, null)
         }
     }
 
     @Composable
     fun Settings(onClick: () -> Unit) {
         IconButton( {
-            Icon(Icons.Filled.Settings)
+            Icon(Icons.Filled.Settings, null)
         }
     }
 }
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
index 47e8e9c..b01334f 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
@@ -88,7 +88,7 @@
         }
         TopAppBar(backgroundColor = appBarColor, contentColor = onSurface) {
             IconButton(modifier = Modifier.align(Alignment.CenterVertically),  {
-                Icon(Icons.Filled.Close)
+                Icon(Icons.Filled.Close, null)
             }
             FilterField(
                 filterText,
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
index 6e2bb73..656fb76 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
@@ -210,6 +210,7 @@
 
     Icon(
         imageVector = vectorResource(R.drawable.ic_plane),
+        contentDescription = stringResource(R.string.plane_description),
         tint = colorResource(R.color.Blue700)
     )
 }
@@ -421,15 +422,16 @@
     }
     object string {
         const val ok = 4
+        const val plane_description = 5
     }
     object dimen {
-        const val padding_small = 5
+        const val padding_small = 6
     }
     object drawable {
-        const val ic_plane = 6
+        const val ic_plane = 7
     }
     object color {
-        const val Blue700 = 7
+        const val Blue700 = 8
     }
 }
 
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt
index f11321f..18ac649 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/navigation/Navigation.kt
@@ -56,11 +56,13 @@
  * No action required if it's modified.
  */
 
-@Composable private fun NavigationSnippet1() {
+@Composable
+private fun NavigationSnippet1() {
     val navController = rememberNavController()
 }
 
-@Composable private fun NavigationSnippet2(navController: NavHostController) {
+@Composable
+private fun NavigationSnippet2(navController: NavHostController) {
     NavHost(navController = navController, startDestination = "profile") {
         composable("profile") { Profile(/*...*/) }
         composable("friendslist") { FriendsList(/*...*/) }
@@ -69,7 +71,8 @@
 }
 
 private object NavigationSnippet3 {
-    @Composable fun Profile(navController: NavController) {
+    @Composable
+    fun Profile(navController: NavController) {
         /*...*/
         Button( navController.navigate("friends") }) {
             Text(text = "Navigate next")
@@ -78,14 +81,16 @@
     }
 }
 
-@Composable private fun NavigationSnippet4(navController: NavHostController) {
+@Composable
+private fun NavigationSnippet4(navController: NavHostController) {
     NavHost(navController = navController, startDestination = "profile/{userId}") {
         /*...*/
         composable("profile/{userId}") { /*...*/ }
     }
 }
 
-@Composable private fun NavigationSnippet5(navController: NavHostController) {
+@Composable
+private fun NavigationSnippet5(navController: NavHostController) {
     NavHost(navController = navController, startDestination = "profile/{userId}") {
         /*...*/
         composable(
@@ -95,17 +100,20 @@
     }
 }
 
-@Composable private fun NavGraphBuilder.NavigationSnippet6(navController: NavHostController) {
+@Composable
+private fun NavGraphBuilder.NavigationSnippet6(navController: NavHostController) {
     composable("profile/{userId}") { backStackEntry ->
         Profile(navController, backStackEntry.arguments?.getString("userId"))
     }
 }
 
-@Composable private fun NavigationSnippet7(navController: NavHostController) {
+@Composable
+private fun NavigationSnippet7(navController: NavHostController) {
     navController.navigate("profile/user1234")
 }
 
-@Composable private fun NavGraphBuilder.NavigationSnippet8(navController: NavHostController) {
+@Composable
+private fun NavGraphBuilder.NavigationSnippet8(navController: NavHostController) {
     composable(
         "profile?userId={userId}",
         arguments = listOf(navArgument("userId") { defaultValue = "me" })
@@ -116,7 +124,8 @@
 
 /* Deep links */
 
-@Composable private fun NavGraphBuilder.NavigationSnippet9(navController: NavHostController) {
+@Composable
+private fun NavGraphBuilder.NavigationSnippet9(navController: NavHostController) {
     val uri = "https://example.com"
 
     composable(
@@ -127,7 +136,8 @@
     }
 }
 
-@Composable private fun NavigationSnippet10() {
+@Composable
+private fun NavigationSnippet10() {
     val id = "exampleId"
     val context = AmbientContext.current
     val deepLinkIntent = Intent(
@@ -143,7 +153,8 @@
     }
 }
 
-@Composable private fun NavigationSnippet11(items: List<Screen>) {
+@Composable
+private fun NavigationSnippet11(items: List<Screen>) {
     val navController = rememberNavController()
     Scaffold(
         bottomBar = {
@@ -152,7 +163,7 @@
                 val currentRoute = navBackStackEntry?.arguments?.getString(KEY_ROUTE)
                 items.forEach { screen ->
                     BottomNavigationItem(
-                        icon = { Icon(Icons.Filled.Favorite) },
+                        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
                         label = { Text(stringResource(screen.resourceId)) },
                         selected = currentRoute == screen.route,
                         >
@@ -178,7 +189,8 @@
     }
 }
 
-@Composable private fun NavGraphBuilder.NavigationSnippet12(navController: NavHostController) {
+@Composable
+private fun NavGraphBuilder.NavigationSnippet12(navController: NavHostController) {
     composable(
         "profile?userId={userId}",
         arguments = listOf(navArgument("userId") { defaultValue = "me" })
@@ -200,12 +212,31 @@
     }
 }
 
-@Composable private fun Profile() { }
-@Composable private fun Profile(userId: String?, content: @Composable (String) -> Unit) { }
-@Composable private fun Profile(navController: NavHostController) { }
-@Composable private fun FriendsList() { }
-@Composable private fun FriendsList(navController: NavHostController) { }
-@Composable private fun Profile(navController: NavHostController, arg: String?) { TODO() }
+@Composable
+private fun Profile() {
+}
+
+@Composable
+private fun Profile(userId: String?, content: @Composable (String) -> Unit) {
+}
+
+@Composable
+private fun Profile(navController: NavHostController) {
+}
+
+@Composable
+private fun FriendsList() {
+}
+
+@Composable
+private fun FriendsList(navController: NavHostController) {
+}
+
+@Composable
+private fun Profile(navController: NavHostController, arg: String?) {
+    TODO()
+}
+
 private class MyActivity
 private sealed class Screen(val route: String, @StringRes val resourceId: Int) {
     object Profile : Screen("profile", R.string.profile)
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
index dd6f636..3d70e48 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
@@ -47,6 +47,7 @@
 import androidx.compose.runtime.savedinstancestate.savedInstanceState
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.viewModel
 import androidx.lifecycle.LiveData
@@ -235,12 +236,18 @@
                     Text(text = body, Modifier.padding(top = 8.dp))
                     // change expanded in response to click events
                     IconButton( expanded = false }, modifier = Modifier.fillMaxWidth()) {
-                        Icon(Icons.Default.ExpandLess)
+                        Icon(
+                            Icons.Default.ExpandLess,
+                            contentDescription = stringResource(R.string.expand_less)
+                        )
                     }
                 } else {
                     // change expanded in response to click events
                     IconButton( expanded = true }, modifier = Modifier.fillMaxWidth()) {
-                        Icon(Icons.Default.ExpandMore)
+                        Icon(
+                            Icons.Default.ExpandMore,
+                            contentDescription = stringResource(R.string.expand_more)
+                        )
                     }
                 }
             }
@@ -284,12 +291,18 @@
                 if (expanded) {
                     Spacer(Modifier.height(8.dp))
                     Text(body)
-                    IconButton( Modifier.fillMaxWidth()) {
-                        Icon(Icons.Default.ExpandLess)
+                    IconButton( modifier = Modifier.fillMaxWidth()) {
+                        Icon(
+                            Icons.Default.ExpandLess,
+                            contentDescription = stringResource(R.string.expand_less)
+                        )
                     }
                 } else {
-                    IconButton( Modifier.fillMaxWidth()) {
-                        Icon(Icons.Default.ExpandMore)
+                    IconButton( modifier = Modifier.fillMaxWidth()) {
+                        Icon(
+                            Icons.Default.ExpandMore,
+                            contentDescription = stringResource(R.string.expand_more)
+                        )
                     }
                 }
             }
@@ -325,6 +338,13 @@
     }
 }
 
+private object R {
+    object string {
+        const val expand_less = 0
+        const val expand_more = 1
+    }
+}
+
 private const val it = 1
 private lateinit var helloViewModel: StateSnippet2.HelloViewModel
 private fun computeTextFormatting(st: String): String = ""
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/tutorial/Tutorial.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/tutorial/Tutorial.kt
index 18a6b75..8cf64b3 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/tutorial/Tutorial.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/tutorial/Tutorial.kt
@@ -159,7 +159,7 @@
         Column(
             modifier = Modifier.padding(16.dp)
         ) {
-            Image(image)
+            Image(image, contentDescription = null)
 
             Text("A day in Shark Fin Cove")
             Text("Davenport, California")
@@ -179,9 +179,12 @@
                 .preferredHeight(180.dp)
                 .fillMaxWidth()
 
-            Image(image,
+            Image(
+                image,
+                contentDescription = null,
                 modifier = imageModifier,
-                contentScale = ContentScale.Crop)
+                contentScale = ContentScale.Crop
+            )
 
             Text("A day in Shark Fin Cove")
             Text("Davenport, California")
@@ -205,9 +208,12 @@
                 .fillMaxWidth()
                 .clip(shape = RoundedCornerShape(4.dp))
 
-            Image(image,
+            Image(
+                image,
+                contentDescription = null,
                 modifier = imageModifier,
-                contentScale = ContentScale.Crop)
+                contentScale = ContentScale.Crop
+            )
             Spacer(Modifier.preferredHeight(16.dp))
 
             Text("A day in Shark Fin Cove")
@@ -230,9 +236,12 @@
                     .fillMaxWidth()
                     .clip(shape = RoundedCornerShape(4.dp))
 
-                Image(image,
+                Image(
+                    image,
+                    contentDescription = null,
                     modifier = imageModifier,
-                    contentScale = ContentScale.Crop)
+                    contentScale = ContentScale.Crop
+                )
                 Spacer(Modifier.preferredHeight(16.dp))
 
                 Text("A day in Shark Fin Cove")
@@ -257,9 +266,12 @@
                     .fillMaxWidth()
                     .clip(shape = RoundedCornerShape(4.dp))
 
-                Image(image,
+                Image(
+                    image,
+                    contentDescription = null,
                     modifier = imageModifier,
-                    contentScale = ContentScale.Crop)
+                    contentScale = ContentScale.Crop
+                )
                 Spacer(Modifier.preferredHeight(16.dp))
 
                 Text("A day in Shark Fin Cove",
@@ -287,9 +299,12 @@
                     .fillMaxWidth()
                     .clip(shape = RoundedCornerShape(4.dp))
 
-                Image(image,
+                Image(
+                    image,
+                    contentDescription = null,
                     modifier = imageModifier,
-                    contentScale = ContentScale.Crop)
+                    contentScale = ContentScale.Crop
+                )
                 Spacer(Modifier.preferredHeight(16.dp))
 
                 Text(
@@ -321,9 +336,11 @@
                     .fillMaxWidth()
                     .clip(shape = RoundedCornerShape(4.dp))
 
-                Image(image,
+                Image(
+                    image, null,
                     modifier = imageModifier,
-                    contentScale = ContentScale.Crop)
+                    contentScale = ContentScale.Crop
+                )
                 Spacer(Modifier.preferredHeight(16.dp))
 
                 Text(
diff --git a/compose/integration-tests/src/androidTest/java/androidx/ui/integration/test/ImageVectorTest.kt b/compose/integration-tests/src/androidTest/java/androidx/ui/integration/test/ImageVectorTest.kt
index 102d854..3e0c8b2 100644
--- a/compose/integration-tests/src/androidTest/java/androidx/ui/integration/test/ImageVectorTest.kt
+++ b/compose/integration-tests/src/androidTest/java/androidx/ui/integration/test/ImageVectorTest.kt
@@ -96,7 +96,7 @@
             }
             val imageVector =
                 vectorResource(R.drawable.ic_pathfill_sample)
-            Image(imageVector, modifier = Modifier.testTag(testTag))
+            Image(imageVector, null, modifier = Modifier.testTag(testTag))
         }
 
         rule.onNodeWithTag(testTag).captureToImage().asAndroidBitmap().apply {
diff --git a/compose/material/material-icons-core/samples/src/main/java/androidx/compose/material/icons/samples/IconSamples.kt b/compose/material/material-icons-core/samples/src/main/java/androidx/compose/material/icons/samples/IconSamples.kt
index 24bd565..36b37ac 100644
--- a/compose/material/material-icons-core/samples/src/main/java/androidx/compose/material/icons/samples/IconSamples.kt
+++ b/compose/material/material-icons-core/samples/src/main/java/androidx/compose/material/icons/samples/IconSamples.kt
@@ -38,7 +38,7 @@
 @Sampled
 @Composable
 fun DrawIcon() {
-    Icon(Icons.Rounded.Menu)
+    Icon(Icons.Rounded.Menu, contentDescription = "Localized description")
 }
 
 @Composable
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index 14adb40..68ce800 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -364,9 +364,9 @@
   }
 
   public final class IconKt {
-    method @androidx.compose.runtime.Composable public static void Icon-1Wn-iBs(androidx.compose.ui.graphics.ImageBitmap bitmap, optional androidx.compose.ui.Modifier modifier, optional long tint);
-    method @androidx.compose.runtime.Composable public static void Icon-1eoVtfs(androidx.compose.ui.graphics.painter.Painter painter, optional androidx.compose.ui.Modifier modifier, optional long tint);
-    method @androidx.compose.runtime.Composable public static void Icon-tu7MLKI(androidx.compose.ui.graphics.vector.ImageVector imageVector, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-8NTYWNk(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-BG621w0(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-hGAziDE(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
   public final class ListItemKt {
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index 14adb40..68ce800 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -364,9 +364,9 @@
   }
 
   public final class IconKt {
-    method @androidx.compose.runtime.Composable public static void Icon-1Wn-iBs(androidx.compose.ui.graphics.ImageBitmap bitmap, optional androidx.compose.ui.Modifier modifier, optional long tint);
-    method @androidx.compose.runtime.Composable public static void Icon-1eoVtfs(androidx.compose.ui.graphics.painter.Painter painter, optional androidx.compose.ui.Modifier modifier, optional long tint);
-    method @androidx.compose.runtime.Composable public static void Icon-tu7MLKI(androidx.compose.ui.graphics.vector.ImageVector imageVector, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-8NTYWNk(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-BG621w0(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-hGAziDE(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
   public final class ListItemKt {
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index 14adb40..68ce800 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -364,9 +364,9 @@
   }
 
   public final class IconKt {
-    method @androidx.compose.runtime.Composable public static void Icon-1Wn-iBs(androidx.compose.ui.graphics.ImageBitmap bitmap, optional androidx.compose.ui.Modifier modifier, optional long tint);
-    method @androidx.compose.runtime.Composable public static void Icon-1eoVtfs(androidx.compose.ui.graphics.painter.Painter painter, optional androidx.compose.ui.Modifier modifier, optional long tint);
-    method @androidx.compose.runtime.Composable public static void Icon-tu7MLKI(androidx.compose.ui.graphics.vector.ImageVector imageVector, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-8NTYWNk(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-BG621w0(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon-hGAziDE(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
   }
 
   public final class ListItemKt {
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ButtonDemo.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ButtonDemo.kt
index 170084f..e07166c 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ButtonDemo.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ButtonDemo.kt
@@ -16,7 +16,7 @@
 
 package androidx.compose.material.demos
 
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
@@ -170,8 +170,8 @@
     var checked by remember { mutableStateOf(false) }
 
     IconToggleButton(checked = checked, enabled = false,  checked = it }) {
-        val tint by animateAsState(if (checked) Color(0xFFEC407A) else Color(0xFFB0BEC5))
-        Icon(Icons.Filled.Favorite, tint = tint)
+        val tint by animateColorAsState(if (checked) Color(0xFFEC407A) else Color(0xFFB0BEC5))
+        Icon(Icons.Filled.Favorite, contentDescription = "Favorite", tint = tint)
     }
 }
 
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt
index babd9ed..8c7a242 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/ColorPickerDemo.kt
@@ -115,7 +115,7 @@
         )
 
         Box(Modifier.fillMaxSize()) {
-            Image(modifier = inputModifier, bitmap = colorWheel.image)
+            Image(modifier = inputModifier, contentDescription = null, bitmap = colorWheel.image)
             val color = colorWheel.colorForPosition(position)
             if (color.isSpecified) {
                 Magnifier(visible = isDragging, position = position, color = color)
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
index b2981c7..dc48864 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
@@ -174,8 +174,12 @@
                                 "Label" + if (selectedOption == Option.Error) "*" else ""
                             Text(text = label)
                         },
-                        leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
-                        trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
+                        leadingIcon = {
+                            if (leadingChecked) Icon(Icons.Filled.Favorite, "Favorite")
+                        },
+                        trailingIcon = {
+                            if (trailingChecked) Icon(Icons.Filled.Info, "Info")
+                        },
                         isErrorValue = selectedOption == Option.Error,
                         modifier = Modifier.width(300.dp)
                     )
@@ -191,8 +195,12 @@
                                 "Label" + if (selectedOption == Option.Error) "*" else ""
                             Text(text = label)
                         },
-                        leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
-                        trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
+                        leadingIcon = {
+                            if (leadingChecked) Icon(Icons.Filled.Favorite, "Favorite")
+                        },
+                        trailingIcon = {
+                            if (trailingChecked) Icon(Icons.Filled.Info, "Info")
+                        },
                         isErrorValue = selectedOption == Option.Error,
                         modifier = Modifier.width(300.dp)
                     )
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MenuDemo.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MenuDemo.kt
index 009a3b3e..eee99c4 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MenuDemo.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MenuDemo.kt
@@ -78,7 +78,7 @@
 
     val iconButton = @Composable {
         IconButton( expanded = true }) {
-            Icon(Icons.Default.MoreVert)
+            Icon(Icons.Default.MoreVert, null)
         }
     }
     DropdownMenu(
diff --git a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/CommonUi.kt b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/CommonUi.kt
index a2ee1ad..423fcc4 100644
--- a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/CommonUi.kt
+++ b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/CommonUi.kt
@@ -100,8 +100,9 @@
         Spacer(Modifier.preferredWidth(16.dp))
         Icon(
             Icons.Filled.ArrowForwardIos,
-            tint = Color.White.copy(alpha = 0.6f),
+            contentDescription = null,
             modifier = Modifier.preferredSize(12.dp).align(Alignment.CenterVertically),
+            tint = Color.White.copy(alpha = 0.6f)
         )
     }
     RallyDivider()
diff --git a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/OverviewScreen.kt b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/OverviewScreen.kt
index 9827abd..8773f93 100644
--- a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/OverviewScreen.kt
+++ b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/OverviewScreen.kt
@@ -33,6 +33,7 @@
 import androidx.compose.material.Text
 import androidx.compose.material.TextButton
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.studies.R
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -40,6 +41,7 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import java.util.Locale
 
@@ -126,7 +128,7 @@
             >
             modifier = Modifier.align(Alignment.Top)
         ) {
-            Icon(Icons.Filled.Sort)
+            Icon(Icons.Filled.Sort, contentDescription = stringResource(R.string.sort))
         }
     }
 }
diff --git a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/RallyScreenState.kt b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/RallyScreenState.kt
index 044c093..ae6e831 100644
--- a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/RallyScreenState.kt
+++ b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/RallyScreenState.kt
@@ -17,14 +17,26 @@
 package androidx.compose.material.studies.rally
 
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.studies.R
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.vector.ImageVector
 
 enum class RallyScreenState(
-    val icon: ImageVector,
+    val icon: ScreenIcon,
     val body: @Composable () -> Unit
 ) {
-    Overview(Icons.Filled.PieChart, { OverviewBody() }),
-    Accounts(Icons.Filled.AttachMoney, { AccountsBody(UserData.accounts) }),
-    Bills(Icons.Filled.MoneyOff, { BillsBody(UserData.bills) })
-}
\ No newline at end of file
+    Overview(
+        ScreenIcon(Icons.Filled.PieChart, contentDescription = R.string.overview),
+        @Composable { OverviewBody() }
+    ),
+    Accounts(
+        ScreenIcon(Icons.Filled.AttachMoney, contentDescription = R.string.account),
+        @Composable { AccountsBody(UserData.accounts) }
+    ),
+    Bills(
+        ScreenIcon(Icons.Filled.MoneyOff, contentDescription = R.string.bills),
+        @Composable { BillsBody(UserData.bills) }
+    )
+}
+
+class ScreenIcon(val icon: ImageVector, val contentDescription: Int)
\ No newline at end of file
diff --git a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/TopAppBar.kt b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/TopAppBar.kt
index 843d7d8..b49e23f 100644
--- a/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/TopAppBar.kt
+++ b/compose/material/material/integration-tests/material-studies/src/main/java/androidx/compose/material/studies/rally/TopAppBar.kt
@@ -38,7 +38,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import java.util.Locale
 
@@ -65,7 +65,7 @@
 @Composable
 private fun RallyTab(
     text: String,
-    icon: ImageVector,
+    icon: ScreenIcon,
     onSelected: () -> Unit,
     selected: Boolean
 ) {
@@ -81,7 +81,11 @@
                     indication = rememberRipple(bounded = false)
                 )
         ) {
-            Icon(icon, tint = tabTintColor)
+            Icon(
+                imageVector = icon.icon,
+                contentDescription = stringResource(icon.contentDescription),
+                tint = tabTintColor
+            )
             if (selected) {
                 Spacer(Modifier.preferredWidth(12.dp))
                 Text(text, color = tabTintColor)
diff --git a/compose/material/material/integration-tests/material-studies/src/main/res/values/strings.xml b/compose/material/material/integration-tests/material-studies/src/main/res/values/strings.xml
new file mode 100644
index 0000000..7df5dd7b
--- /dev/null
+++ b/compose/material/material/integration-tests/material-studies/src/main/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="sort">Sort</string>
+    <string name="overview">Account overview</string>
+    <string name="account">Accounts</string>
+    <string name="bills">Bills</string>
+</resources>
\ No newline at end of file
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/AppBarSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/AppBarSamples.kt
index 1019531..2d17900 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/AppBarSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/AppBarSamples.kt
@@ -36,16 +36,16 @@
         title = { Text("Simple TopAppBar") },
         navigationIcon = {
             IconButton( /* doSomething() */ }) {
-                Icon(Icons.Filled.Menu)
+                Icon(Icons.Filled.Menu, contentDescription = null)
             }
         },
         actions = {
             // RowScope here, so these icons will be placed horizontally
             IconButton( /* doSomething() */ }) {
-                Icon(Icons.Filled.Favorite)
+                Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
             }
             IconButton( /* doSomething() */ }) {
-                Icon(Icons.Filled.Favorite)
+                Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
             }
         }
     )
@@ -56,15 +56,15 @@
 fun SimpleBottomAppBar() {
     BottomAppBar {
         IconButton( /* doSomething() */ }) {
-            Icon(Icons.Filled.Menu)
+            Icon(Icons.Filled.Menu, contentDescription = "Localized description")
         }
         // The actions should be at the end of the BottomAppBar
         Spacer(Modifier.weight(1f, true))
         IconButton( /* doSomething() */ }) {
-            Icon(Icons.Filled.Favorite)
+            Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
         }
         IconButton( /* doSomething() */ }) {
-            Icon(Icons.Filled.Favorite)
+            Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
         }
     }
 }
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt
index 368287d..6895b34 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BackdropScaffoldSamples.kt
@@ -58,11 +58,11 @@
                 navigationIcon = {
                     if (scaffoldState.isConcealed) {
                         IconButton( scaffoldState.reveal() }) {
-                            Icon(Icons.Default.Menu)
+                            Icon(Icons.Default.Menu, contentDescription = "Localized description")
                         }
                     } else {
                         IconButton( scaffoldState.conceal() }) {
-                            Icon(Icons.Default.Close)
+                            Icon(Icons.Default.Close, contentDescription = "Localized description")
                         }
                     }
                 },
@@ -77,7 +77,7 @@
                             }
                         }
                     ) {
-                        Icon(Icons.Default.Favorite)
+                        Icon(Icons.Default.Favorite, contentDescription = "Localized description")
                     }
                 },
                 elevation = 0.dp,
@@ -103,7 +103,12 @@
                 items(50) {
                     ListItem(
                         text = { Text("Item $it") },
-                        icon = { Icon(Icons.Default.Favorite) }
+                        icon = {
+                            Icon(
+                                Icons.Default.Favorite,
+                                contentDescription = "Localized description"
+                            )
+                        }
                     )
                 }
             }
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomNavigationSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomNavigationSamples.kt
index 321d4bc..b51b529 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomNavigationSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomNavigationSamples.kt
@@ -38,7 +38,7 @@
     BottomNavigation {
         items.forEachIndexed { index, item ->
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
                 label = { Text(item) },
                 selected = selectedItem == index,
                  selectedItem = index }
@@ -55,7 +55,7 @@
     BottomNavigation {
         items.forEachIndexed { index, item ->
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
                 label = { Text(item) },
                 selected = selectedItem == index,
                  selectedItem = index },
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomSheetScaffoldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomSheetScaffoldSamples.kt
index 8ef6b56..3a39938 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomSheetScaffoldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/BottomSheetScaffoldSamples.kt
@@ -89,7 +89,7 @@
                 title = { Text("Bottom sheet scaffold") },
                 navigationIcon = {
                     IconButton( scaffoldState.drawerState.open() }) {
-                        Icon(Icons.Default.Menu)
+                        Icon(Icons.Default.Menu, contentDescription = "Localized description")
                     }
                 }
             )
@@ -104,7 +104,7 @@
                     }
                 }
             ) {
-                Icon(Icons.Default.Favorite)
+                Icon(Icons.Default.Favorite, contentDescription = "Localized description")
             }
         },
         floatingActionButtonPosition = FabPosition.End,
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ButtonSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ButtonSamples.kt
index 12cfe41..3539c00 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ButtonSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ButtonSamples.kt
@@ -58,7 +58,11 @@
 @Composable
 fun ButtonWithIconSample() {
     Button( /* Do something! */ }) {
-        Icon(Icons.Filled.Favorite, Modifier.size(ButtonDefaults.IconSize))
+        Icon(
+            Icons.Filled.Favorite,
+            contentDescription = null,
+            modifier = Modifier.size(ButtonDefaults.IconSize)
+        )
         Spacer(Modifier.size(ButtonDefaults.IconSpacing))
         Text("Like")
     }
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/FloatingActionButtonSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/FloatingActionButtonSamples.kt
index a90c6a5..da257ea 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/FloatingActionButtonSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/FloatingActionButtonSamples.kt
@@ -31,7 +31,7 @@
 @Composable
 fun SimpleFab() {
     FloatingActionButton( /*do something*/ }) {
-        Icon(Icons.Filled.Favorite)
+        Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
     }
 }
 
@@ -47,7 +47,7 @@
 @Composable
 fun SimpleExtendedFabWithIcon() {
     ExtendedFloatingActionButton(
-        icon = { Icon(Icons.Filled.Favorite) },
+        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
         text = { Text("ADD TO BASKET") },
          /*do something*/ }
     )
@@ -57,7 +57,7 @@
 @Composable
 fun FluidExtendedFab() {
     ExtendedFloatingActionButton(
-        icon = { Icon(Icons.Filled.Favorite) },
+        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
         text = { Text("FLUID FAB") },
          /*do something*/ },
         modifier = Modifier.fillMaxWidth()
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/IconButtonSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/IconButtonSamples.kt
index 84ac071..847dbb1 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/IconButtonSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/IconButtonSamples.kt
@@ -17,7 +17,7 @@
 package androidx.compose.material.samples
 
 import androidx.annotation.Sampled
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.material.Icon
 import androidx.compose.material.IconButton
 import androidx.compose.material.IconToggleButton
@@ -34,7 +34,7 @@
 @Composable
 fun IconButtonSample() {
     IconButton( /* doSomething() */ }) {
-        Icon(Icons.Filled.Favorite)
+        Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
     }
 }
 
@@ -44,7 +44,7 @@
     var checked by remember { mutableStateOf(false) }
 
     IconToggleButton(checked = checked,  checked = it }) {
-        val tint by animateAsState(if (checked) Color(0xFFEC407A) else Color(0xFFB0BEC5))
-        Icon(Icons.Filled.Favorite, tint = tint)
+        val tint by animateColorAsState(if (checked) Color(0xFFEC407A) else Color(0xFFB0BEC5))
+        Icon(Icons.Filled.Favorite, contentDescription = "Localized description", tint = tint)
     }
 }
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
index 88f67fd..c41ca94 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ListSamples.kt
@@ -104,17 +104,35 @@
         Divider()
         ListItem(
             text = { Text("One line list item with 24x24 icon") },
-            icon = { Image(icon24x24, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon24x24,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
             text = { Text("One line list item with 40x40 icon") },
-            icon = { Image(icon40x40, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon40x40,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
             text = { Text("One line list item with 56x56 icon") },
-            icon = { Image(icon56x56, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon56x56,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
@@ -122,6 +140,7 @@
             icon = {
                 Image(
                     icon56x56,
+                    contentDescription = null,
                     colorFilter = ColorFilter.tint(AmbientContentColor.current)
                 )
             },
@@ -130,7 +149,7 @@
         Divider()
         ListItem(
             text = { Text("One line list item with trailing icon") },
-            trailing = { Icon(vectorIcon) }
+            trailing = { Icon(vectorIcon, contentDescription = "Localized description") }
         )
         Divider()
         ListItem(
@@ -138,10 +157,11 @@
             icon = {
                 Image(
                     icon40x40,
+                    contentDescription = null,
                     colorFilter = ColorFilter.tint(AmbientContentColor.current)
                 )
             },
-            trailing = { Icon(vectorIcon) }
+            trailing = { Icon(vectorIcon, contentDescription = "Localized description") }
         )
         Divider()
     }
@@ -165,13 +185,25 @@
         ListItem(
             text = { Text("Two line list item with 24x24 icon") },
             secondaryText = { Text("Secondary text") },
-            icon = { Image(icon24x24, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon24x24,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
             text = { Text("Two line list item with 40x40 icon") },
             secondaryText = { Text("Secondary text") },
-            icon = { Image(icon40x40, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon40x40,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
@@ -181,6 +213,7 @@
             icon = {
                 Image(
                     icon40x40,
+                    contentDescription = null,
                     colorFilter = ColorFilter.tint(AmbientContentColor.current)
                 )
             }
@@ -220,7 +253,13 @@
                 )
             },
             singleLineSecondaryText = false,
-            icon = { Image(icon24x24, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon24x24,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
@@ -232,7 +271,7 @@
                 )
             },
             singleLineSecondaryText = false,
-            trailing = { Icon(vectorIcon) }
+            trailing = { Icon(vectorIcon, "Localized description") }
         )
         Divider()
         ListItem(
@@ -254,12 +293,24 @@
         Divider()
         ListItem(
             text = { Text("פריט ברשימה אחת עם תמונה.") },
-            icon = { Image(icon40x40, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon40x40,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
             text = { Text("One line list item with 24x24 icon") },
-            icon = { Image(icon40x40, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon40x40,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
         ListItem(
@@ -267,6 +318,7 @@
             trailing = {
                 Image(
                     icon24x24,
+                    contentDescription = null,
                     colorFilter = ColorFilter.tint(AmbientContentColor.current)
                 )
             }
@@ -300,6 +352,7 @@
             icon = {
                 Image(
                     icon40x40,
+                    contentDescription = null,
                     colorFilter = ColorFilter.tint(AmbientContentColor.current)
                 )
             }
@@ -311,6 +364,7 @@
             icon = {
                 Image(
                     icon40x40,
+                    contentDescription = null,
                     colorFilter = ColorFilter.tint(AmbientContentColor.current)
                 )
             },
@@ -345,7 +399,13 @@
             text = { Text("ثلاثة عناصر قائمة مع رمز") },
             overlineText = { Text("فوق الخط") },
             secondaryText = { Text("نص ثانوي") },
-            icon = { Image(icon40x40, colorFilter = ColorFilter.tint(AmbientContentColor.current)) }
+            icon = {
+                Image(
+                    icon40x40,
+                    contentDescription = null,
+                    colorFilter = ColorFilter.tint(AmbientContentColor.current)
+                )
+            }
         )
         Divider()
     }
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/MenuSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/MenuSamples.kt
index d423bd0..433bfbc 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/MenuSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/MenuSamples.kt
@@ -42,7 +42,7 @@
 
     val iconButton = @Composable {
         IconButton( expanded = true }) {
-            Icon(Icons.Default.MoreVert)
+            Icon(Icons.Default.MoreVert, contentDescription = "Localized description")
         }
     }
     DropdownMenu(
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ModalBottomSheetSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ModalBottomSheetSamples.kt
index 9c63c0e..40ce474 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ModalBottomSheetSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ModalBottomSheetSamples.kt
@@ -50,7 +50,12 @@
                 items(50) {
                     ListItem(
                         text = { Text("Item $it") },
-                        icon = { Icon(Icons.Default.Favorite) }
+                        icon = {
+                            Icon(
+                                Icons.Default.Favorite,
+                                contentDescription = "Localized description"
+                            )
+                        }
                     )
                 }
             }
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ProgressIndicatorSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ProgressIndicatorSamples.kt
index 6fb006f..b7bcac5 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ProgressIndicatorSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ProgressIndicatorSamples.kt
@@ -17,7 +17,7 @@
 package androidx.compose.material.samples
 
 import androidx.annotation.Sampled
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.height
@@ -39,7 +39,7 @@
 @Composable
 fun LinearProgressIndicatorSample() {
     var progress by remember { mutableStateOf(0.1f) }
-    val animatedProgress by animateAsState(
+    val animatedProgress by animateFloatAsState(
         targetValue = progress,
         animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
     )
@@ -61,7 +61,7 @@
 @Composable
 fun CircularProgressIndicatorSample() {
     var progress by remember { mutableStateOf(0.1f) }
-    val animatedProgress by animateAsState(
+    val animatedProgress by animateFloatAsState(
         targetValue = progress,
         animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
     )
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt
index df7666e..1b95b94 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt
@@ -91,7 +91,7 @@
                             scaffoldState.drawerState.open()
                         }
                     ) {
-                        Icon(Icons.Filled.Menu)
+                        Icon(Icons.Filled.Menu, contentDescription = "Localized description")
                     }
                 }
             )
@@ -161,7 +161,7 @@
                         scaffoldState.drawerState.open()
                     }
                 ) {
-                    Icon(Icons.Filled.Menu)
+                    Icon(Icons.Filled.Menu, contentDescription = "Localized description")
                 }
             }
         },
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
index 4a896c2..a10706d 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SwipeToDismissSamples.kt
@@ -17,8 +17,9 @@
 package androidx.compose.material.samples
 
 import androidx.annotation.Sampled
-import androidx.compose.animation.animateAsState
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.animation.core.animateDpAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -98,7 +99,7 @@
                 },
                 background = {
                     val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
-                    val color by animateAsState(
+                    val color by animateColorAsState(
                         when (dismissState.targetValue) {
                             Default -> Color.LightGray
                             DismissedToEnd -> Color.Green
@@ -113,7 +114,7 @@
                         StartToEnd -> Icons.Default.Done
                         EndToStart -> Icons.Default.Delete
                     }
-                    val scale by animateAsState(
+                    val scale by animateFloatAsState(
                         if (dismissState.targetValue == Default) 0.75f else 1f
                     )
 
@@ -121,12 +122,16 @@
                         Modifier.fillMaxSize().background(color).padding(horizontal = 20.dp),
                         contentAlignment = alignment
                     ) {
-                        Icon(icon, Modifier.scale(scale))
+                        Icon(
+                            icon,
+                            contentDescription = "Localized description",
+                            modifier = Modifier.scale(scale)
+                        )
                     }
                 },
                 dismissContent = {
                     Card(
-                        elevation = animateAsState(
+                        elevation = animateDpAsState(
                             if (dismissState.dismissDirection != null) 4.dp else 0.dp
                         ).value
                     ) {
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TabSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TabSamples.kt
index af55358..a61e589 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TabSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TabSamples.kt
@@ -87,7 +87,7 @@
         TabRow(selectedTabIndex = state) {
             icons.forEachIndexed { index, icon ->
                 Tab(
-                    icon = { Icon(icon) },
+                    icon = { Icon(icon, contentDescription = "Favorite") },
                     selected = state == index,
                      state = index }
                 )
@@ -114,7 +114,7 @@
             titlesAndIcons.forEachIndexed { index, (title, icon) ->
                 Tab(
                     text = { Text(title) },
-                    icon = { Icon(icon) },
+                    icon = { Icon(icon, contentDescription = null) },
                     selected = state == index,
                      state = index }
                 )
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt
index 83553c1..f631a97 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextFieldSamples.kt
@@ -75,8 +75,8 @@
         value = text,
          text = it },
         placeholder = { Text("placeholder") },
-        leadingIcon = { Icon(Icons.Filled.Favorite) },
-        trailingIcon = { Icon(Icons.Filled.Info) }
+        leadingIcon = { Icon(Icons.Filled.Favorite, contentDescription = "Localized description") },
+        trailingIcon = { Icon(Icons.Filled.Info, contentDescription = "Localized description") }
     )
 }
 
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AppBarTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AppBarTest.kt
index 05b8283..39baeaf 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AppBarTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/AppBarTest.kt
@@ -198,7 +198,7 @@
      */
     private val FakeIcon = @Composable { modifier: Modifier ->
         IconButton( modifier = modifier) {
-            Icon(ColorPainter(Color.Red))
+            Icon(ColorPainter(Color.Red), null)
         }
     }
 
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationScreenshotTest.kt
index b32d261..c347707 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationScreenshotTest.kt
@@ -316,18 +316,18 @@
     Box(Modifier.semantics(mergeDescendants = true) {}.testTag(Tag)) {
         BottomNavigation {
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 selected = true,
                 >
                 interactionState = interactionState
             )
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 selected = false,
                 >
             )
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 selected = false,
                 >
             )
@@ -359,7 +359,7 @@
     Box(Modifier.semantics(mergeDescendants = true) {}.testTag(Tag)) {
         BottomNavigation(backgroundColor = backgroundColor) {
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 selected = true,
                 >
                 interactionState = interactionState,
@@ -367,14 +367,14 @@
                 unselectedContentColor = unselectedContentColor
             )
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 selected = false,
                 >
                 selectedContentColor = selectedContentColor,
                 unselectedContentColor = unselectedContentColor
             )
             BottomNavigationItem(
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 selected = false,
                 >
                 selectedContentColor = selectedContentColor,
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationTest.kt
index 107384f..dcdef28 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomNavigationTest.kt
@@ -81,7 +81,7 @@
                 BottomNavigation {
                     repeat(4) { index ->
                         BottomNavigationItem(
-                            icon = { Icon(Icons.Filled.Favorite) },
+                            icon = { Icon(Icons.Filled.Favorite, null) },
                             label = { Text("Item $index") },
                             selected = index == 0,
                             >
@@ -119,7 +119,7 @@
                     BottomNavigationItem(
                         modifier = Modifier.testTag("item"),
                         icon = {
-                            Icon(Icons.Filled.Favorite, Modifier.testTag("icon"))
+                            Icon(Icons.Filled.Favorite, null, Modifier.testTag("icon"))
                         },
                         label = {
                             Text("ItemText")
@@ -164,7 +164,7 @@
                     BottomNavigationItem(
                         modifier = Modifier.testTag("item"),
                         icon = {
-                            Icon(Icons.Filled.Favorite, Modifier.testTag("icon"))
+                            Icon(Icons.Filled.Favorite, null, Modifier.testTag("icon"))
                         },
                         label = {
                             Text("ItemText")
@@ -198,7 +198,7 @@
                     BottomNavigationItem(
                         modifier = Modifier.testTag("item"),
                         icon = {
-                            Icon(Icons.Filled.Favorite, Modifier.testTag("icon"))
+                            Icon(Icons.Filled.Favorite, null, Modifier.testTag("icon"))
                         },
                         label = {},
                         selected = false,
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
index 7349c2a..9cc7ffc 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/BottomSheetScaffoldTest.kt
@@ -327,7 +327,7 @@
                             }.testTag(fabTag),
                         >
                     ) {
-                        Icon(Icons.Filled.Favorite)
+                        Icon(Icons.Filled.Favorite, null)
                     }
                 },
                 bodyContent = { Text("Content") }
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
index 10d8101..c00a8b0 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
@@ -65,7 +65,7 @@
         rule.setMaterialContent {
             Box {
                 FloatingActionButton(modifier = Modifier.testTag("myButton"),  {
-                    Icon(Icons.Filled.Favorite)
+                    Icon(Icons.Filled.Favorite, null)
                 }
             }
         }
@@ -99,7 +99,7 @@
         rule
             .setMaterialContentForSizeAssertions {
                 FloatingActionButton( {
-                    Icon(Icons.Filled.Favorite)
+                    Icon(Icons.Filled.Favorite, null)
                 }
             }
             .assertIsSquareWithSize(56.dp)
@@ -111,7 +111,7 @@
             ExtendedFloatingActionButton(
                 modifier = Modifier.testTag("FAB"),
                 text = { Text("Extended FAB Text") },
-                icon = { Icon(Icons.Filled.Favorite) },
+                icon = { Icon(Icons.Filled.Favorite, null) },
                 >
             )
         }
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt
index 9953c9c..dea21b2 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/IconTest.kt
@@ -30,6 +30,7 @@
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.AmbientDensity
 import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.test.assertHeightIsEqualTo
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.captureToImage
@@ -41,6 +42,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -58,7 +60,7 @@
         val vector = Icons.Filled.Menu
         rule
             .setMaterialContentForSizeAssertions {
-                Icon(vector)
+                Icon(vector, null)
             }
             .assertWidthIsEqualTo(width)
             .assertHeightIsEqualTo(height)
@@ -74,7 +76,7 @@
         ).build()
         rule
             .setMaterialContentForSizeAssertions {
-                Icon(vector)
+                Icon(vector, null)
             }
             .assertWidthIsEqualTo(width)
             .assertHeightIsEqualTo(height)
@@ -90,7 +92,7 @@
                     ImageBitmap(width.toIntPx(), height.toIntPx())
                 }
 
-                Icon(image)
+                Icon(image, null)
             }
             .assertWidthIsEqualTo(width)
             .assertHeightIsEqualTo(height)
@@ -107,7 +109,7 @@
                     ImageBitmap(width.toIntPx(), height.toIntPx())
                 }
 
-                Icon(image)
+                Icon(image, null)
             }
             .assertWidthIsEqualTo(width)
             .assertHeightIsEqualTo(height)
@@ -120,7 +122,7 @@
         val painter = ColorPainter(Color.Red)
         rule
             .setMaterialContentForSizeAssertions {
-                Icon(painter)
+                Icon(painter, null)
             }
             .assertWidthIsEqualTo(width)
             .assertHeightIsEqualTo(height)
@@ -138,7 +140,7 @@
                 }
 
                 val imagePainter = ImagePainter(image)
-                Icon(imagePainter)
+                Icon(imagePainter, null)
             }
             .assertWidthIsEqualTo(width)
             .assertHeightIsEqualTo(height)
@@ -160,7 +162,7 @@
                     Color.Red
                 )
             }
-            Icon(image, modifier = Modifier.testTag(testTag), tint = Color.Unspecified)
+            Icon(image, null, modifier = Modifier.testTag(testTag), tint = Color.Unspecified)
         }
 
         // With no color provided for a tint, the icon should render the original pixels
@@ -183,13 +185,31 @@
                     Color.Red
                 )
             }
-            Icon(image, modifier = Modifier.testTag(testTag), tint = Color.Blue)
+            Icon(image, null, modifier = Modifier.testTag(testTag), tint = Color.Blue)
         }
 
         // With a tint color provided, all pixels should be blue
         rule.onNodeWithTag(testTag).captureToImage().assertPixels { Color.Blue }
     }
 
+    @Test
+    fun contentDescriptionAppliedToIcon() {
+        val testTag = "TestTag"
+        rule.setContent {
+            Icon(
+                bitmap = ImageBitmap(100, 100),
+                contentDescription = "qwerty",
+                modifier = Modifier.testTag(testTag)
+            )
+        }
+
+        rule.onNodeWithTag(testTag).fetchSemanticsNode().let {
+            assertThat(it.config.contains(SemanticsProperties.ContentDescription)).isTrue()
+            assertThat(it.config[SemanticsProperties.ContentDescription])
+                .isEqualTo("qwerty")
+        }
+    }
+
     private fun createBitmapWithColor(
         density: Density,
         width: Int,
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt
index a3588ff..087e32e 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ListItemTest.kt
@@ -71,7 +71,7 @@
             .setMaterialContentForSizeAssertions {
                 ListItem(
                     text = { Text("Primary text") },
-                    icon = { Icon(icon24x24) }
+                    icon = { Icon(icon24x24, null) }
                 )
             }
             .assertHeightIsEqualTo(expectedHeightSmallIcon)
@@ -85,7 +85,7 @@
             .setMaterialContentForSizeAssertions {
                 ListItem(
                     text = { Text("Primary text") },
-                    icon = { Icon(icon56x56) }
+                    icon = { Icon(icon56x56, null) }
                 )
             }
             .assertHeightIsEqualTo(expectedHeightLargeIcon)
@@ -115,7 +115,7 @@
                 ListItem(
                     text = { Text("Primary text") },
                     secondaryText = { Text("Secondary text") },
-                    icon = { Icon(icon24x24) }
+                    icon = { Icon(icon24x24, null) }
                 )
             }
             .assertHeightIsEqualTo(expectedHeightWithIcon)
@@ -199,7 +199,7 @@
                 ListItem(
                     text = { Text("Primary text", Modifier.saveLayout(textPosition, textSize)) },
                     trailing = {
-                        Image(icon24x24, Modifier.saveLayout(trailingPosition, trailingSize))
+                        Image(icon24x24, null, Modifier.saveLayout(trailingPosition, trailingSize))
                     }
                 )
             }
@@ -238,7 +238,7 @@
             Box {
                 ListItem(
                     text = { Text("Primary text", Modifier.saveLayout(textPosition, textSize)) },
-                    icon = { Image(icon24x24, Modifier.saveLayout(iconPosition, iconSize)) }
+                    icon = { Image(icon24x24, null, Modifier.saveLayout(iconPosition, iconSize)) }
                 )
             }
         }
@@ -365,7 +365,7 @@
                         )
                     },
                     icon = {
-                        Image(icon24x24, Modifier.saveLayout(iconPosition, iconSize))
+                        Image(icon24x24, null, Modifier.saveLayout(iconPosition, iconSize))
                     }
                 )
             }
@@ -436,10 +436,10 @@
                         )
                     },
                     icon = {
-                        Image(icon40x40, Modifier.saveLayout(iconPosition, iconSize))
+                        Image(icon40x40, null, Modifier.saveLayout(iconPosition, iconSize))
                     },
                     trailing = {
-                        Image(icon24x24, Modifier.saveLayout(trailingPosition, trailingSize))
+                        Image(icon24x24, null, Modifier.saveLayout(trailingPosition, trailingSize))
                     }
                 )
             }
@@ -518,10 +518,10 @@
                     },
                     singleLineSecondaryText = false,
                     icon = {
-                        Image(icon24x24, Modifier.saveLayout(iconPosition, iconSize))
+                        Image(icon24x24, null, Modifier.saveLayout(iconPosition, iconSize))
                     },
                     trailing = {
-                        Image(icon24x24, Modifier.saveLayout(trailingPosition, trailingSize))
+                        Image(icon24x24, null, Modifier.saveLayout(trailingPosition, trailingSize))
                     }
                 )
             }
@@ -613,6 +613,7 @@
                     icon = {
                         Image(
                             icon40x40,
+                            null,
                             Modifier.saveLayout(iconPosition, iconSize)
                         )
                     },
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt
index 872efe4..9600b81 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldScreenshotTest.kt
@@ -623,7 +623,7 @@
             val cutoutShape = if (fabCutout) CircleShape else null
             BottomAppBar(cutoutShape = cutoutShape) {
                 IconButton( {
-                    Icon(Icons.Filled.Menu)
+                    Icon(Icons.Filled.Menu, null)
                 }
             }
         }
@@ -645,7 +645,7 @@
     val fab = @Composable {
         if (showFab) {
             FloatingActionButton(
-                content = { Icon(Icons.Filled.Favorite) },
+                content = { Icon(Icons.Filled.Favorite, null) },
                 >
             )
         }
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt
index aa6181f0..d33dc24 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ScaffoldTest.kt
@@ -285,7 +285,7 @@
                         },
                         >
                     ) {
-                        Icon(Icons.Filled.Favorite)
+                        Icon(Icons.Filled.Favorite, null)
                     }
                 },
                 floatingActionButtonPosition = FabPosition.Center,
@@ -321,7 +321,7 @@
                         },
                         >
                     ) {
-                        Icon(Icons.Filled.Favorite)
+                        Icon(Icons.Filled.Favorite, null)
                     }
                 },
                 floatingActionButtonPosition = FabPosition.End,
@@ -394,7 +394,7 @@
                         },
                         >
                     ) {
-                        Icon(Icons.Filled.Favorite)
+                        Icon(Icons.Filled.Favorite, null)
                     }
                 }
             }
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/TabTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/TabTest.kt
index 65e2389..ea0bd06 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/TabTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/TabTest.kt
@@ -114,7 +114,7 @@
     fun iconTab_height() {
         rule
             .setMaterialContentForSizeAssertions {
-                Tab(icon = { Icon(icon) }, selected = true, >
+                Tab(icon = { Icon(icon, null) }, selected = true, >
             }
             .assertHeightIsEqualTo(ExpectedSmallTabHeight)
     }
@@ -126,7 +126,7 @@
                 Surface {
                     Tab(
                         text = { Text("Text and Icon") },
-                        icon = { Icon(icon) },
+                        icon = { Icon(icon, null) },
                         selected = true,
                         >
                     )
@@ -245,7 +245,7 @@
                             text = {
                                 Text(title, Modifier.testTag("text"))
                             },
-                            icon = { Icon(Icons.Filled.Favorite) },
+                            icon = { Icon(Icons.Filled.Favorite, null) },
                             selected = state == index,
                              state = index }
                         )
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BackdropScaffold.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BackdropScaffold.kt
index d244464..c1890e6 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BackdropScaffold.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BackdropScaffold.kt
@@ -21,7 +21,7 @@
 import androidx.compose.animation.core.AnimationEndReason.Interrupted
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -378,7 +378,7 @@
     visible: Boolean
 ) {
     if (color != Color.Transparent) {
-        val alpha by animateAsState(
+        val alpha by animateFloatAsState(
             targetValue = if (visible) 1f else 0f,
             animationSpec = TweenSpec()
         )
@@ -407,7 +407,7 @@
 ) {
     // The progress of the animation between Revealed (0) and Concealed (2).
     // The midpoint (1) is the point where the appBar and backContent are switched.
-    val animationProgress by animateAsState(
+    val animationProgress by animateFloatAsState(
         targetValue = if (target == Revealed) 0f else 2f, animationSpec = TweenSpec()
     )
     val animationSlideOffset = with(AmbientDensity.current) { AnimationSlideOffset.toPx() }
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BottomNavigation.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BottomNavigation.kt
index 8dbe44b..743d369 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BottomNavigation.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/BottomNavigation.kt
@@ -19,7 +19,7 @@
 import androidx.compose.animation.core.FastOutSlowInEasing
 import androidx.compose.animation.core.TweenSpec
 import androidx.compose.animation.core.VectorizedAnimationSpec
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.Interaction
 import androidx.compose.foundation.InteractionState
 import androidx.compose.foundation.layout.Arrangement
@@ -204,7 +204,7 @@
     selected: Boolean,
     content: @Composable (animationProgress: Float) -> Unit
 ) {
-    val animationProgress by animateAsState(
+    val animationProgress by animateFloatAsState(
         targetValue = if (selected) 1f else 0f,
         animationSpec = BottomNavigationAnimationSpec
     )
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
index 78915f1..134ff10 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
@@ -16,7 +16,7 @@
 
 package androidx.compose.material
 
-import androidx.compose.animation.animateAsState
+import androidx.compose.animation.animateColorAsState
 import androidx.compose.animation.core.FloatPropKey
 import androidx.compose.animation.core.TransitionSpec
 import androidx.compose.animation.core.keyframes
@@ -365,7 +365,7 @@
         }
 
         val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
-        return animateAsState(target, tween(durationMillis = duration))
+        return animateColorAsState(target, tween(durationMillis = duration))
     }
 
     @Composable
@@ -387,7 +387,7 @@
         // enabled / disabled.
         return if (enabled) {
             val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
-            animateAsState(target, tween(durationMillis = duration))
+            animateColorAsState(target, tween(durationMillis = duration))
         } else {
             rememberUpdatedState(target)
         }
@@ -411,7 +411,7 @@
         // enabled / disabled.
         return if (enabled) {
             val duration = if (state == ToggleableState.Off) BoxOutDuration else BoxInDuration
-            animateAsState(target, tween(durationMillis = duration))
+            animateColorAsState(target, tween(durationMillis = duration))
         } else {
             rememberUpdatedState(target)
         }
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt
index e21c901..aeb0954 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Icon.kt
@@ -31,6 +31,8 @@
 import androidx.compose.ui.graphics.toolingGraphicsLayer
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.graphics.vector.rememberVectorPainter
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.dp
 
 /**
@@ -38,6 +40,10 @@
  * clickable icon, see [IconButton].
  *
  * @param imageVector [ImageVector] to draw inside this Icon
+ * @param contentDescription text used by accessibility services to describe what this icon
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
  * @param modifier optional [Modifier] for this Icon
  * @param tint tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no
  *  tint is applied
@@ -45,11 +51,13 @@
 @Composable
 fun Icon(
     imageVector: ImageVector,
+    contentDescription: String?,
     modifier: Modifier = Modifier,
     tint: Color = AmbientContentColor.current.copy(alpha = AmbientContentAlpha.current)
 ) {
     Icon(
         painter = rememberVectorPainter(imageVector),
+        contentDescription = contentDescription,
         modifier = modifier,
         tint = tint
     )
@@ -60,6 +68,10 @@
  * clickable icon, see [IconButton].
  *
  * @param bitmap [ImageBitmap] to draw inside this Icon
+ * @param contentDescription text used by accessibility services to describe what this icon
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
  * @param modifier optional [Modifier] for this Icon
  * @param tint tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no
  *  tint is applied
@@ -67,12 +79,14 @@
 @Composable
 fun Icon(
     bitmap: ImageBitmap,
+    contentDescription: String?,
     modifier: Modifier = Modifier,
     tint: Color = AmbientContentColor.current
 ) {
     val painter = remember(bitmap) { ImagePainter(bitmap) }
     Icon(
         painter = painter,
+        contentDescription = contentDescription,
         modifier = modifier,
         tint = tint
     )
@@ -83,6 +97,10 @@
  * clickable icon, see [IconButton].
  *
  * @param painter [Painter] to draw inside this Icon
+ * @param contentDescription text used by accessibility services to describe what this icon
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
  * @param modifier optional [Modifier] for this Icon
  * @param tint tint to be applied to [painter]. If [Color.Unspecified] is provided, then no
  *  tint is applied
@@ -90,6 +108,7 @@
 @Composable
 fun Icon(
     painter: Painter,
+    contentDescription: String?,
     modifier: Modifier = Modifier,
     tint: Color = AmbientContentColor.current.copy(alpha = AmbientContentAlpha.current)
 ) {
@@ -97,9 +116,15 @@
     // size that this icon will be forced to take up.
     // TODO: b/149735981 semantics for content description
     val colorFilter = if (tint == Color.Unspecified) null else ColorFilter.tint(tint)
+    val semantics = if (contentDescription != null) {
+        Modifier.semantics { this.contentDescription = contentDescription }
+    } else {
+        Modifier
+    }
     Box(
         modifier.toolingGraphicsLayer().defaultSizeFor(painter)
             .paint(painter, colorFilter = colorFilter)
+            .then(semantics)
     )
 }
 
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt
index 3ea26dd..1c4d33a 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt
@@ -21,7 +21,7 @@
 import androidx.compose.animation.core.AnimationEndReason
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -287,7 +287,7 @@
     visible: Boolean
 ) {
     if (color != Color.Transparent) {
-        val alpha by animateAsState(
+        val alpha by animateFloatAsState(
             targetValue = if (visible) 1f else 0f,
             animationSpec = TweenSpec()
         )
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt
index 97bc87e..feb68ad 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/RadioButton.kt
@@ -16,8 +16,8 @@
 
 package androidx.compose.material
 
-import androidx.compose.animation.animateAsState
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.animation.core.animateDpAsState
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.Interaction
@@ -77,7 +77,7 @@
     interactionState: InteractionState = remember { InteractionState() },
     colors: RadioButtonColors = RadioButtonDefaults.colors()
 ) {
-    val dotRadius by animateAsState(
+    val dotRadius by animateDpAsState(
         targetValue = if (selected) RadioButtonDotSize / 2 else 0.dp,
         animationSpec = tween(durationMillis = RadioAnimationDuration)
     )
@@ -182,7 +182,7 @@
         // If not enabled 'snap' to the disabled state, as there should be no animations between
         // enabled / disabled.
         return if (enabled) {
-            animateAsState(target, tween(durationMillis = RadioAnimationDuration))
+            animateColorAsState(target, tween(durationMillis = RadioAnimationDuration))
         } else {
             rememberUpdatedState(target)
         }
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Tab.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Tab.kt
index ddba4a7..cf5d043 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Tab.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Tab.kt
@@ -19,7 +19,7 @@
 import androidx.compose.animation.animateColor
 import androidx.compose.animation.core.FastOutSlowInEasing
 import androidx.compose.animation.core.LinearEasing
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateDpAsState
 import androidx.compose.animation.core.tween
 import androidx.compose.animation.core.updateTransition
 import androidx.compose.animation.transition
@@ -226,7 +226,7 @@
         // TODO: should we animate the width of the indicator as it moves between tabs of different
         // sizes inside a scrollable tab row?
         val currentTabWidth = currentTabPosition.width
-        val indicatorOffset by animateAsState(
+        val indicatorOffset by animateDpAsState(
             targetValue = currentTabPosition.left,
             animationSpec = tween(durationMillis = 250, easing = FastOutSlowInEasing)
         )
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index 6afaa39..c11c1a0 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -21,6 +21,7 @@
   }
 
   public final class ActualJvmKt {
+    method @kotlin.PublishedApi internal static inline <R> R! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends R> block);
   }
 
   @androidx.compose.runtime.Stable public abstract sealed class Ambient<T> {
@@ -242,6 +243,7 @@
   }
 
   public final class ExpectKt {
+    method @kotlin.PublishedApi internal static inline <R> R! synchronized(Object lock, kotlin.jvm.functions.Function0<? extends R> block);
   }
 
   @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level, message="This is an experimental API for Compose and is likely to change before becoming " + "stable.") @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget}) public @interface ExperimentalComposeApi {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt
index 31c52b0..9edecf5 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt
@@ -30,6 +30,7 @@
 
 internal expect fun identityHashCode(instance: Any?): Int
 
+@PublishedApi
 internal expect inline fun <R> synchronized(lock: Any, block: () -> R): R
 
 expect class AtomicReference<V>(value: V) {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
index 6f68340..8deda49 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
@@ -22,6 +22,7 @@
 import androidx.compose.runtime.ExperimentalComposeApi
 import androidx.compose.runtime.InternalComposeApi
 import androidx.compose.runtime.ThreadLocal
+import androidx.compose.runtime.synchronized
 
 /**
  * Take a snapshot of the current value of all state objects. The values are preserved until
@@ -1362,7 +1363,6 @@
 internal val lock = Any()
 
 @PublishedApi
-@Suppress("DEPRECATION_ERROR")
 internal inline fun <T> sync(block: () -> T): T = synchronized(lock, block)
 
 // The following variables should only be written when sync is taken
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
index 07f89e2..2c4a5ae 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
@@ -20,9 +20,9 @@
 import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.TestOnly
 import androidx.compose.runtime.collection.IdentityScopeMap
+import androidx.compose.runtime.synchronized
 
 @ExperimentalComposeApi
-@Suppress("DEPRECATION_ERROR")
 class SnapshotStateObserver(private val onChangedExecutor: (callback: () -> Unit) -> Unit) {
     private val applyObserver: SnapshotApplyObserver = { applied, _ ->
         var hasValues = false
diff --git a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.kt b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.kt
index 830f020..e61fdc6 100644
--- a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.kt
+++ b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.kt
@@ -39,10 +39,9 @@
 
 internal actual fun identityHashCode(instance: Any?): Int = System.identityHashCode(instance)
 
+@PublishedApi
 internal actual inline fun <R> synchronized(lock: Any, block: () -> R): R {
-    kotlin.synchronized(lock) {
-        return block()
-    }
+    return kotlin.synchronized(lock, block)
 }
 
 internal actual typealias TestOnly = org.jetbrains.annotations.TestOnly
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/TestAnimationPreview.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/TestAnimationPreview.kt
index 232a23f..17e63cf 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/TestAnimationPreview.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/TestAnimationPreview.kt
@@ -71,6 +71,6 @@
         shape = MaterialTheme.shapes.large.copy(topLeft = CornerSize(state[CheckBoxCorner])),
         modifier = Modifier.toggleable(value = selected, >
     ) {
-        Icon(imageVector = Icons.Filled.Done)
+        Icon(imageVector = Icons.Filled.Done, contentDescription = null)
     }
 }
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt
index 2c25f26..eeb8a85 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt
@@ -93,7 +93,7 @@
             Inspectable(slotTableRecord) {
                 Column {
                     Text(text = "Hello World", color = Color.Green)
-                    Icon(Icons.Filled.FavoriteBorder)
+                    Icon(Icons.Filled.FavoriteBorder, null)
                     Surface {
                         Button( { Text(text = "OK") }
                     }
@@ -309,7 +309,7 @@
                 Column {
                     Text(text = "Hello World", color = Color.Green)
                     Spacer(Modifier.preferredHeight(16.dp))
-                    Image(Icons.Filled.Call)
+                    Image(Icons.Filled.Call, null)
                 }
             }
         }
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/VectorGraphicsDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/VectorGraphicsDemo.kt
index 8465693..5686f60 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/VectorGraphicsDemo.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/VectorGraphicsDemo.kt
@@ -51,6 +51,7 @@
         imageVector.resource.resource?.let {
             Image(
                 imageVector = it,
+                contentDescription = "Crane",
                 modifier = Modifier.preferredSize(200.dp, 200.dp),
                 contentScale = ContentScale.Inside
             )
@@ -60,6 +61,7 @@
         complexImageVector.resource.resource?.let {
             Image(
                 imageVector = it,
+                contentDescription = "Hourglass",
                 modifier = Modifier.preferredSize(64.dp, 64.dp),
                 contentScale = ContentScale.Fit
             )
@@ -67,6 +69,7 @@
 
         Image(
             painter = vectorShape(120.dp, 120.dp),
+            contentDescription = null,
             modifier = Modifier.preferredSize(200.dp, 150.dp)
         )
     }
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/ReuseFocusReference.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/ReuseFocusReference.kt
index bfcbed2..bd96ca8 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/ReuseFocusReference.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/ReuseFocusReference.kt
@@ -17,7 +17,7 @@
 package androidx.compose.ui.demos.focus
 
 import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
@@ -76,7 +76,7 @@
 @Composable
 private fun Circle(modifier: Modifier = Modifier, nextShape: () -> Unit) {
     var isFocused by remember { mutableStateOf(false) }
-    val scale by animateAsState(if (isFocused) 0f else 1f, TweenSpec(2000)) {
+    val scale by animateFloatAsState(if (isFocused) 0f else 1f, TweenSpec(2000)) {
         if (it == 0f) {
             nextShape()
         }
@@ -99,7 +99,7 @@
 @Composable
 private fun Square(modifier: Modifier = Modifier, nextShape: () -> Unit) {
     var isFocused by remember { mutableStateOf(false) }
-    val scale by animateAsState(if (isFocused) 0f else 1f, TweenSpec(2000)) {
+    val scale by animateFloatAsState(if (isFocused) 0f else 1f, TweenSpec(2000)) {
         if (it == 0f) {
             nextShape()
         }
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt
index 15c1dbd..cb5f8ad 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/DrawModifierSample.kt
@@ -111,6 +111,7 @@
     }
     Image(
         painter = vectorPainter,
+        contentDescription = null,
         modifier = Modifier.size(120.dp).drawWithCache {
             val gradient = Brush.linearGradient(
                 colors = listOf(Color.Red, Color.Blue),
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PainterSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PainterSample.kt
index dfce282..48f7a8e 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PainterSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PainterSample.kt
@@ -66,6 +66,7 @@
     // in the landscape orientation based on the res/drawable and res/drawable-land-hdpi folders
     Image(
         painterResource(R.drawable.ic_vector_or_png),
+        contentDescription = null,
         modifier = Modifier.size(50.dp)
     )
 }
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
index cc50b9a..00f8ee8 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
@@ -29,7 +29,7 @@
 import android.widget.FrameLayout
 import android.widget.LinearLayout
 import androidx.annotation.RequiresApi
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -3005,7 +3005,7 @@
             activity.setContent {
                 Box(Modifier.background(Color.Red).drawLatchModifier()) {
                     var animatedSize by remember { mutableStateOf(size) }
-                    animatedSize = animateAsState(size).value
+                    animatedSize = animateFloatAsState(size).value
                     if (animatedSize == 10f) {
                         Layout(
                             modifier = Modifier.background(Color.Cyan),
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt
index 66d65f3..3847526 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt
@@ -233,13 +233,14 @@
             val clickState = remember { mutableStateOf(false) }
             Image(
                 imageVector = if (clickState.value) icon1 else icon2,
+                contentDescription = null,
                 modifier = Modifier
                     .testTag(testTag)
                     .preferredSize(icon1.defaultWidth, icon1.defaultHeight)
                     .background(Color.Red)
                     .clickable { clickState.value = !clickState.value },
-                contentScale = ContentScale.FillHeight,
-                alignment = Alignment.TopStart
+                alignment = Alignment.TopStart,
+                contentScale = ContentScale.FillHeight
             )
         }
 
@@ -292,6 +293,7 @@
             }
             Image(
                 painter = vectorPainter,
+                contentDescription = null,
                 modifier = Modifier
                     .testTag(testTag)
                     .preferredSize(defaultWidth * 7, defaultHeight * 3)
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt
index 73e2715..186a2b0 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnSizeChangedTest.kt
@@ -92,6 +92,43 @@
     }
 
     @Test
+    @SmallTest
+    fun internalSizeChange() {
+        var latch = CountDownLatch(1)
+        var changedSize = IntSize.Zero
+        var sizePx by mutableStateOf(10)
+
+        rule.runOnUiThread {
+            activity.setContent {
+                with(AmbientDensity.current) {
+                    Box(
+                        Modifier.padding(10.toDp())
+                            .onSizeChanged {
+                                changedSize = it
+                                latch.countDown()
+                            }.padding(sizePx.toDp())
+                    ) {
+                        Box(Modifier.size(10.toDp()))
+                    }
+                }
+            }
+        }
+
+        // Initial setting will call onSizeChanged
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        assertEquals(30, changedSize.height)
+        assertEquals(30, changedSize.width)
+
+        latch = CountDownLatch(1)
+        sizePx = 20
+
+        // We've changed the size of the contents, so we should receive a onSizeChanged call
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        assertEquals(50, changedSize.height)
+        assertEquals(50, changedSize.width)
+    }
+
+    @Test
     fun onlyInnerSizeChange() {
         var latch = CountDownLatch(1)
         var changedSize = IntSize.Zero
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnRemeasuredModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnRemeasuredModifier.kt
index 338fcaf..90d7e8b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnRemeasuredModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/OnRemeasuredModifier.kt
@@ -23,14 +23,17 @@
 import androidx.compose.ui.unit.IntSize
 
 /**
- * Invoke [onSizeChanged] with the size of the content after it has been measured.
- * This will only be invoked either the first time measurement happens or when the content
+ * Invoke [onSizeChanged] when the size of the modifier immediately after it has changed. If
+ * there is no modifier following [onSizeChanged], the content size of the layout is reported.
+ *
+ * [onSizeChanged] will only be invoked during the first time measurement or when the
  * size has changed.
  *
- * Use [Layout] or [SubcomposeLayout] to have the size of one component to affect the size
+ * Use [Layout] or [SubcomposeLayout] to have the size of one component affect the size
  * of another component. Using the size received from the [onSizeChanged] callback in a
  * [MutableState] to affect layout will cause the new value to be recomposed and read only in the
- * following frame, causing a one frame lag.
+ * following frame, causing a one frame lag. You can use [onSizeChanged] to affect
+ * drawing operations.
  *
  * Example usage:
  * @sample androidx.compose.ui.samples.OnSizeChangedSample
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index 7f1d771..c4b79fe 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -60,7 +60,6 @@
 import androidx.compose.ui.semantics.outerSemantics
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.util.deleteAt
 import kotlin.math.roundToInt
@@ -642,7 +641,6 @@
             }
             val addedCallback = hasNewPositioningCallback()
             onPositionedCallbacks.clear()
-            onRemeasuredCallbacks.clear()
 
             // Create a new chain of LayoutNodeWrappers, reusing existing ones from wrappers
             // when possible.
@@ -651,9 +649,6 @@
                 if (mod is OnGloballyPositionedModifier) {
                     onPositionedCallbacks += mod
                 }
-                if (mod is OnRemeasuredModifier) {
-                    onRemeasuredCallbacks += mod
-                }
                 if (mod is RemeasurementModifier) {
                     mod.onRemeasurementAvailable(this)
                 }
@@ -699,6 +694,9 @@
                     if (mod is SemanticsModifier) {
                         wrapper = SemanticsWrapper(wrapper, mod).assignChained(toWrap)
                     }
+                    if (mod is OnRemeasuredModifier) {
+                        wrapper = RemeasureModifierWrapper(wrapper, mod).assignChained(toWrap)
+                    }
                 }
                 wrapper
             }
@@ -770,11 +768,6 @@
     private val >
 
     /**
-     * List of all OnSizeChangedModifiers in the modifier chain.
-     */
-    private val >
-
-    /**
      * Flag used by [OnPositionedDispatcher] to identify LayoutNodes that have already
      * had their [OnGloballyPositionedModifier]'s dispatch called so that they aren't called
      * multiple times.
@@ -1070,16 +1063,6 @@
         innerLayoutNodeWrapper.measureResult = measureResult
         this.providedAlignmentLines.clear()
         this.providedAlignmentLines += measureResult.alignmentLines
-
-        if (onRemeasuredCallbacks.isNotEmpty()) {
-            val invokeRemeasureCallbacks = {
-                val content = innerLayoutNodeWrapper
-                val size = IntSize(content.measuredWidth, content.measuredHeight)
-                onRemeasuredCallbacks.forEach { it.onRemeasured(size) }
-            }
-            owner?.snapshotObserver?.pauseSnapshotReadObservation(invokeRemeasureCallbacks)
-                ?: invokeRemeasureCallbacks.invoke()
-        }
     }
 
     /**
@@ -1389,4 +1372,4 @@
         wrapper.isChained = true
     }
     return this
-}
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RemeasureModifierWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RemeasureModifierWrapper.kt
new file mode 100644
index 0000000..6d25308
--- /dev/null
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RemeasureModifierWrapper.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.node
+
+import androidx.compose.ui.layout.OnRemeasuredModifier
+import androidx.compose.ui.layout.Placeable
+import androidx.compose.ui.unit.Constraints
+
+/**
+ * Wrapper around the [OnRemeasuredModifier] to notify whenever a remeasurement happens.
+ */
+internal class RemeasureModifierWrapper(
+    wrapped: LayoutNodeWrapper,
+    modifier: OnRemeasuredModifier
+) : DelegatingLayoutNodeWrapper<OnRemeasuredModifier>(wrapped, modifier) {
+    override fun performMeasure(constraints: Constraints): Placeable {
+        val placeable = super.performMeasure(constraints)
+        val invokeRemeasureCallbacks = {
+            modifier.onRemeasured(measuredSize)
+        }
+        layoutNode.owner?.snapshotObserver?.pauseSnapshotReadObservation(invokeRemeasureCallbacks)
+            ?: invokeRemeasureCallbacks.invoke()
+        return placeable
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
index 9bac865..950d856 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.TweenSpec
-import androidx.compose.animation.core.animateAsState
+import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
@@ -214,7 +214,7 @@
         var targetValue by mutableStateOf(10f)
 
         setContent {
-            val value by animateAsState(
+            val value by animateFloatAsState(
                 targetValue,
                 animationSpec = TweenSpec(durationMillis = 30, easing = LinearEasing)
             )
diff --git a/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt b/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt
new file mode 100644
index 0000000..a2a7689
--- /dev/null
+++ b/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.datastore.core
+
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
+import kotlinx.coroutines.ensureActive
+import kotlinx.coroutines.launch
+import java.util.concurrent.atomic.AtomicInteger
+
+internal class SimpleActor<T>(
+    /**
+     * The scope in which to consume messages.
+     */
+    private val scope: CoroutineScope,
+    /**
+     * Function that will be called when scope is cancelled.
+     */
+    onComplete: (Throwable?) -> Unit,
+    /**
+     * Function that will be called once for each message.
+     *
+     * Must *not* throw an exception (other than CancellationException if scope is cancelled).
+     */
+    private val consumeMessage: suspend (T) -> Unit
+) {
+    private val messageQueue = Channel<T>(capacity = UNLIMITED)
+    private val remainingMessages = AtomicInteger(0)
+
+    init {
+        // If the scope doesn't have a job, it won't be cancelled, so we don't need to register a
+        // callback.
+        scope.coroutineContext[Job]?.invokeOnCompletion { ex ->
+            onComplete(ex)
+            messageQueue.cancel()
+        }
+    }
+
+    fun offer(msg: T) {
+        /**
+         * Possible states:
+         * 1) No active consumer and remaining=0
+         *     This will happen when there are no remaining messages to receive in the channel
+         *     and there is no one actively sending.
+         * 2) No active consumer and remaining>0
+         *     This will only happen after a new send call after state 1. The new sender
+         *     incremented the count, and must send a message to the queue and is responsible for
+         *     starting a new consumer (state 3).
+         * 3) Active consumer and remaining>0
+         *     The consumer must continue to process messages until it sees that there are no
+         *     remaining messages, at which point it will revert to state 1.
+         */
+
+        // If the number of remaining messages was 0, there is no consumer, since it quits
+        // consuming once remaining messages hits 0. We must kick off a new consumer.
+        val shouldReLaunch = remainingMessages.getAndIncrement() == 0
+
+        check(messageQueue.offer(msg)) // should never fail bc the channel capacity is unlimited
+
+        if (shouldReLaunch) {
+            scope.launch {
+                // We shouldn't have started a new consumer unless there are remaining messages...
+                check(remainingMessages.get() > 0)
+
+                do {
+                    // We don't want to try to consume a new message unless we are still active.
+                    // If ensureActive throws, the scope is no longer active, so it doesn't
+                    // matter that we have remaining messages.
+                    scope.ensureActive()
+
+                    consumeMessage(messageQueue.receive())
+                } while (remainingMessages.decrementAndGet() != 0)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/datastore/datastore-core/src/main/java/androidx/datastore/core/SingleProcessDataStore.kt b/datastore/datastore-core/src/main/java/androidx/datastore/core/SingleProcessDataStore.kt
index a7a831e..e2f02e1 100644
--- a/datastore/datastore-core/src/main/java/androidx/datastore/core/SingleProcessDataStore.kt
+++ b/datastore/datastore-core/src/main/java/androidx/datastore/core/SingleProcessDataStore.kt
@@ -16,16 +16,14 @@
 package androidx.datastore.core
 
 import androidx.datastore.core.handlers.NoOpCorruptionHandler
+import kotlinx.coroutines.CancellationException
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.FlowPreview
-import kotlinx.coroutines.ObsoleteCoroutinesApi
 import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
 import kotlinx.coroutines.channels.ConflatedBroadcastChannel
-import kotlinx.coroutines.channels.SendChannel
 import kotlinx.coroutines.channels.actor
 import kotlinx.coroutines.completeWith
 import kotlinx.coroutines.flow.Flow
@@ -59,7 +57,7 @@
 /**
  * Single process implementation of DataStore. This is NOT multi-process safe.
  */
-@OptIn(ExperimentalCoroutinesApi::class, ObsoleteCoroutinesApi::class, FlowPreview::class)
+@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
 internal class SingleProcessDataStore<T>(
     private val produceFile: () -> File,
     private val serializer: Serializer<T>,
@@ -86,7 +84,7 @@
         val dataChannel = downstreamChannel()
         val updateMsg = Message.Update<T>(transform, ack, dataChannel, coroutineContext)
 
-        actor.send(updateMsg)
+        actor.offer(updateMsg)
 
         // If no read has succeeded yet, we need to wait on the result of the next read so we can
         // bubble exceptions up to the caller. Read exceptions are not bubbled up through ack.
@@ -142,38 +140,39 @@
     /**
      * Consumes messages. All state changes should happen within actor.
      */
-    private val actor: SendChannel<Message<T>> = scope.actor(
-        capacity = UNLIMITED
-    ) {
-        try {
-            messageConsumer@ for (msg in channel) {
-                if (msg.dataChannel.isClosedForSend) {
-                    // The message was sent with an old, now closed, dataChannel. This means that
-                    // our read failed.
-                    continue@messageConsumer
-                }
-
-                try {
-                    readAndInitOnce(msg.dataChannel)
-                } catch (ex: Throwable) {
-                    resetDataChannel(ex)
-                    continue@messageConsumer
-                }
-
-                // We have successfully read data and sent it to downstreamChannel.
-
-                if (msg is Message.Update) {
-                    msg.ack.completeWith(
-                        runCatching {
-                            transformAndWrite(msg.transform, downstreamChannel(), msg.callerContext)
-                        }
-                    )
-                }
-            }
-        } finally {
+    private val actor = SimpleActor<Message<T>>(
+        scope = scope,
+        >
             // The scope has been cancelled. Cancel downstream in case there are any collectors
             // still active.
-            downstreamChannel().cancel()
+            if (it is CancellationException) {
+                downstreamChannel().cancel(it)
+            } else if (it is Throwable) {
+                downstreamChannel().close(it)
+            }
+        }
+    ) { msg ->
+        if (msg.dataChannel.isClosedForSend) {
+            // The message was sent with an old, now closed, dataChannel. This means that
+            // our read failed.
+            return@SimpleActor
+        }
+
+        try {
+            readAndInitOnce(msg.dataChannel)
+        } catch (ex: Throwable) {
+            resetDataChannel(ex)
+            return@SimpleActor
+        }
+
+        // We have successfully read data and sent it to downstreamChannel.
+
+        if (msg is Message.Update) {
+            msg.ack.completeWith(
+                runCatching {
+                    transformAndWrite(msg.transform, downstreamChannel(), msg.callerContext)
+                }
+            )
         }
     }
 
diff --git a/datastore/datastore-core/src/test/java/androidx/datastore/core/SimpleActorTest.kt b/datastore/datastore-core/src/test/java/androidx/datastore/core/SimpleActorTest.kt
new file mode 100644
index 0000000..702abb1
--- /dev/null
+++ b/datastore/datastore-core/src/test/java/androidx/datastore/core/SimpleActorTest.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.datastore.core
+
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.Test
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicBoolean
+import kotlin.coroutines.AbstractCoroutineContextElement
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.coroutineContext
+
+@ExperimentalCoroutinesApi
+class SimpleActorTest {
+    @Test
+    fun testSimpleActor() = runBlockingTest {
+        val msgs = mutableListOf<Int>()
+
+        val actor = SimpleActor<Int>(
+            this,
+            >
+        ) {
+            msgs.add(it)
+        }
+
+        actor.offer(1)
+        actor.offer(2)
+        actor.offer(3)
+        actor.offer(4)
+
+        assertThat(msgs).isEqualTo(listOf(1, 2, 3, 4))
+    }
+
+    @Test
+    fun testOnCompleteIsCalledWhenScopeIsCancelled() = runBlocking<Unit> {
+        val scope = CoroutineScope(Job())
+        val called = AtomicBoolean(false)
+
+        val actor = SimpleActor<Int>(
+            scope,
+            >
+                assertThat(called.compareAndSet(false, true)).isTrue()
+            }
+        ) {
+            // do nothing
+        }
+
+        actor.offer(123)
+
+        scope.coroutineContext[Job]!!.cancelAndJoin()
+
+        assertThat(called.get()).isTrue()
+    }
+
+    @Test
+    fun testManyConcurrentCalls() = runBlocking<Unit> {
+        val scope = CoroutineScope(Job() + Executors.newFixedThreadPool(4).asCoroutineDispatcher())
+        val numCalls = 100000
+        val volatileIntHolder = VolatileIntHolder()
+
+        val latch = CountDownLatch(numCalls)
+        val actor = SimpleActor<Int>(scope,  {
+            val newValue = volatileIntHolder.int + 1
+            // This should be safe because there shouldn't be any concurrent calls
+            volatileIntHolder.int = newValue
+            latch.countDown()
+        }
+
+        repeat(numCalls) {
+            scope.launch {
+                actor.offer(it)
+            }
+        }
+
+        latch.await(5, TimeUnit.SECONDS)
+
+        assertThat(volatileIntHolder.int).isEqualTo(numCalls)
+    }
+
+    @Test
+    fun testManyConcurrentCalls_withDelayBeforeSettingValue() = runBlocking<Unit> {
+        val scope = CoroutineScope(Job() + Executors.newFixedThreadPool(4).asCoroutineDispatcher())
+        val numCalls = 500
+        val volatileIntHolder = VolatileIntHolder()
+
+        val latch = CountDownLatch(numCalls)
+        val actor = SimpleActor<Int>(scope,  {
+            val newValue = volatileIntHolder.int + 1
+            delay(1)
+            // This should be safe because there shouldn't be any concurrent calls
+            volatileIntHolder.int = newValue
+            latch.countDown()
+        }
+
+        repeat(numCalls) {
+            scope.launch {
+                actor.offer(it)
+            }
+        }
+
+        latch.await(5, TimeUnit.SECONDS)
+
+        assertThat(volatileIntHolder.int).isEqualTo(numCalls)
+    }
+
+    @Test
+    fun testMessagesAreConsumedInProvidedScope() = runBlocking {
+        val scope = CoroutineScope(TestElement("test123"))
+        val latch = CompletableDeferred<Unit>()
+
+        val actor = SimpleActor<Int>(scope,  {
+            assertThat(getTestElement().name).isEqualTo("test123")
+            latch.complete(Unit)
+        }
+
+        actor.offer(123)
+
+        latch.await()
+    }
+
+    class TestElement(val name: String) : AbstractCoroutineContextElement(Key) {
+        companion object Key : CoroutineContext.Key<TestElement>
+    }
+
+    private suspend fun getTestElement(): TestElement {
+        return coroutineContext[TestElement]!!
+    }
+
+    private class VolatileIntHolder {
+        @Volatile
+        var int = 0
+    }
+}
\ No newline at end of file
diff --git a/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreTest.kt b/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreTest.kt
index b8c7ded..ac1dca1 100644
--- a/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreTest.kt
+++ b/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreTest.kt
@@ -301,7 +301,10 @@
         dataStoreScope.cancel()
 
         assertThrows<CancellationException> { slowUpdate.await() }
+
         assertThrows<CancellationException> { notStartedUpdate.await() }
+
+        assertThrows<CancellationException> { store.updateData { 123 } }
     }
 
     @Test
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index 8a6e871..072e510 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -420,6 +420,9 @@
 WARNING: Illegal reflective access by androidx\.room\.compiler\.processing\.javac\.JavacProcessingEnvMessager\$Companion\$isFromCompiledClass\$[0-9]+ \(file:\$OUT_DIR/androidx/room/room\-compiler\-processing/build/libs/room\-compiler\-processing\-[0-9]+\.[0-9]+\.[0-9]+\-alpha[0-9]+\.jar\) to field com\.sun\.tools\.javac\.code\.Symbol\$ClassSymbol\.classfile
 WARNING: Please consider reporting this to the maintainers of androidx\.room\.compiler\.processing\.javac\.JavacProcessingEnvMessager\$Companion\$isFromCompiledClass\$[0-9]+
 # > Task :wear:wear-watchface-complications-rendering:compileDebugUnitTestJavaWithJavac
+# > Task :wear:wear-watchface:testDebugUnitTest
+System\.logW\: A resource was acquired at attached stack trace but never released\. See java\.io\.Closeable for information on avoiding resource leaks\.java\.lang\.Throwable\: Explicit termination method \'dispose\' not called
+System\.logW\: A resource was acquired at attached stack trace but never released\. See java\.io\.Closeable for information on avoiding resource leaks\.java\.lang\.Throwable\: Explicit termination method \'release\' not called
 # > Task :benchmark:benchmark-perfetto:mergeDebugAndroidTestJavaResource
 More than one file was found with OS independent path '.*'\. This version of the Android Gradle Plugin chooses the file from the app or dynamic\-feature module, but this can cause unexpected behavior or errors at runtime\. Future versions of the Android Gradle Plugin will throw an error in this case\.
 # > Task :docs-runner:dokkaJavaTipOfTreeDocs
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index 146b6ca..e134e44 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -35,6 +35,7 @@
     docs(project(":camera:camera-lifecycle"))
     docs(project(":camera:camera-view"))
     docs(project(":car:app:app"))
+    docs(project(":car:app:app-aaos"))
     docs(project(":cardview:cardview"))
     docs(project(":collection:collection"))
     docs(project(":collection:collection-ktx"))
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
index 04ce980..0008abd 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.java
@@ -230,9 +230,9 @@
             Animation anim = Preconditions.checkNotNull(
                     Preconditions.checkNotNull(animationInfo.getAnimation(context)).animation);
             Operation.State finalState = operation.getFinalState();
-            if (finalState == Operation.State.VISIBLE) {
-                // If we've moving to VISIBLE, we can't use a AnimationSet
-                // due that causing the introduction of visual artifacts (b/163084315).
+            if (finalState != Operation.State.REMOVED) {
+                // If the operation does not remove the view, we can't use a
+                // AnimationSet due that causing the introduction of visual artifacts (b/163084315).
                 viewToAnimate.startAnimation(anim);
                 // This means we can't use setAnimationListener() without overriding
                 // any listener that the Fragment has set themselves, so we
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java b/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
index 8cccb82..e370f53 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DialogFragment.java
@@ -95,6 +95,10 @@
     private static final String SAVED_CANCELABLE = "android:cancelable";
     private static final String SAVED_SHOWS_DIALOG = "android:showsDialog";
     private static final String SAVED_BACK_STACK_ID = "android:backStackId";
+    /**
+     * Copied from {@link Dialog}.
+     */
+    private static final String SAVED_INTERNAL_DIALOG_SHOWING = "android:dialogShowing";
 
     private Handler mHandler;
     private Runnable mDismissRunnable = new Runnable() {
@@ -691,6 +695,7 @@
         super.onSaveInstanceState(outState);
         if (mDialog != null) {
             Bundle dialogState = mDialog.onSaveInstanceState();
+            dialogState.putBoolean(SAVED_INTERNAL_DIALOG_SHOWING, false);
             outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState);
         }
         if (mStyle != STYLE_NORMAL) {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
index 64fa88e..99bf534 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -3305,7 +3305,7 @@
                             RouteInfo route = new RouteInfo(provider, groupId, uniqueId);
                             route.maybeUpdateDescriptor(groupRouteDescriptor);
 
-                            if (mSelectedRoute != route) {
+                            if (mSelectedRoute == route) {
                                 return;
                             }
 
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.java b/navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.kt
similarity index 91%
rename from navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.java
rename to navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.kt
index f9f0fbb..167dcb1 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.java
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavArgs.kt
@@ -13,11 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package androidx.navigation;
+package androidx.navigation
 
 /**
  * An interface marking generated Args classes.
  */
-public interface NavArgs {
-}
+public interface NavArgs
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NoOpNavigator.java b/navigation/navigation-common/src/main/java/androidx/navigation/NoOpNavigator.java
deleted file mode 100644
index a4ed438..0000000
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NoOpNavigator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.navigation;
-
-import android.os.Bundle;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
-
-/**
- * A {@link Navigator} that only supports creating destinations.
- *
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-@Navigator.Name("NoOp")
-public class NoOpNavigator extends Navigator<NavDestination> {
-    @NonNull
-    @Override
-    public NavDestination createDestination() {
-        return new NavDestination(this);
-    }
-
-    @Nullable
-    @Override
-    public NavDestination navigate(@NonNull NavDestination destination, @Nullable Bundle args,
-            @Nullable NavOptions navOptions, @Nullable Extras navigatorExtras) {
-        return destination;
-    }
-
-    @Override
-    public boolean popBackStack() {
-        return true;
-    }
-}
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NoOpNavigator.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NoOpNavigator.kt
new file mode 100644
index 0000000..044db7a
--- /dev/null
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NoOpNavigator.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.navigation
+
+import android.os.Bundle
+import androidx.annotation.RestrictTo
+
+/**
+ * A [Navigator] that only supports creating destinations.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@Navigator.Name("NoOp")
+public class NoOpNavigator : Navigator<NavDestination>() {
+    override fun createDestination(): NavDestination = NavDestination(this)
+
+    override fun navigate(
+        destination: NavDestination,
+        args: Bundle?,
+        navOptions: NavOptions?,
+        navigatorExtras: Extras?
+    ): NavDestination? = destination
+
+    override fun popBackStack(): Boolean = true
+}
diff --git a/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/BottomBarNavDemo.kt b/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/BottomBarNavDemo.kt
index 5367b9f..7c3f3159c 100644
--- a/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/BottomBarNavDemo.kt
+++ b/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/BottomBarNavDemo.kt
@@ -53,7 +53,7 @@
                 val entryRoute = navBackStackEntry?.arguments?.getString(KEY_ROUTE)
                 items.forEach { (name, route) ->
                     BottomNavigationItem(
-                        icon = { Icon(Icons.Filled.Favorite) },
+                        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
                         label = { Text(name) },
                         selected = entryRoute == route,
                         >
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
index 9e5dc62..1c9b115 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavBackStackEntryLifecycleTest.kt
@@ -861,6 +861,45 @@
             .isEqualTo(Lifecycle.State.RESUMED)
     }
 
+    @UiThreadTest
+    @Test
+    fun testLifecycleToDestroyedWhenInitialized() {
+        val navController = createNavController(TestLifecycleOwner(Lifecycle.State.INITIALIZED))
+        val navGraph = navController.navigatorProvider.navigation(
+            id = 1,
+            startDestination = R.id.start_test
+        ) {
+            test(R.id.start_test)
+            test(R.id.second_test)
+        }
+        navController.graph = navGraph
+
+        val startBackStackEntry = navController.getBackStackEntry(R.id.start_test)
+        assertWithMessage("The start destination should be initialized")
+            .that(startBackStackEntry.lifecycle.currentState)
+            .isEqualTo(Lifecycle.State.INITIALIZED)
+
+        navController.navigate(R.id.second_test)
+
+        val secondBackStackEntry = navController.getBackStackEntry(R.id.second_test)
+        assertWithMessage("The new destination should be initialized")
+            .that(secondBackStackEntry.lifecycle.currentState)
+            .isEqualTo(Lifecycle.State.INITIALIZED)
+
+        navController.popBackStack()
+
+        assertWithMessage("The popped destination should be initialized")
+            .that(secondBackStackEntry.lifecycle.currentState)
+            .isEqualTo(Lifecycle.State.INITIALIZED)
+
+        // Pop the last destination off the stack
+        navController.popBackStack()
+
+        assertWithMessage("The start destination should be initialized after pop")
+            .that(startBackStackEntry.lifecycle.currentState)
+            .isEqualTo(Lifecycle.State.INITIALIZED)
+    }
+
     private fun createNavController(
         lifecycleOwner: LifecycleOwner = TestLifecycleOwner(Lifecycle.State.RESUMED)
     ): NavController {
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
index 7c6c27b..afd3cf0 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.java
@@ -324,7 +324,9 @@
         for (Navigator<?> navigator : popOperations) {
             if (navigator.popBackStack()) {
                 NavBackStackEntry entry = mBackStack.removeLast();
-                entry.setMaxLifecycle(Lifecycle.State.DESTROYED);
+                if (entry.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.CREATED)) {
+                    entry.setMaxLifecycle(Lifecycle.State.DESTROYED);
+                }
                 if (mViewModel != null) {
                     mViewModel.clear(entry.mId);
                 }
diff --git a/settings.gradle b/settings.gradle
index 982c21b..cae4b3a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -159,6 +159,7 @@
 includeProject(":benchmark:integration-tests:startup-benchmark", "benchmark/integration-tests/startup-benchmark", [BuildType.MAIN])
 includeProject(":biometric:biometric", "biometric/biometric", [BuildType.MAIN])
 includeProject(":biometric:biometric-ktx", "biometric/biometric-ktx", [BuildType.MAIN])
+includeProject(":biometric:biometric-ktx-samples", "biometric/biometric-ktx/samples", [BuildType.MAIN])
 includeProject(":biometric:integration-tests:testapp", "biometric/integration-tests/testapp", [BuildType.MAIN])
 includeProject(":browser:browser", "browser/browser", [BuildType.MAIN])
 includeProject(":buildSrc-tests", "buildSrc-tests", [BuildType.MAIN])
@@ -186,6 +187,7 @@
 includeProject(":camera:integration-tests:camera-testapp-view", "camera/integration-tests/viewtestapp", [BuildType.MAIN])
 includeProject(":camera:integration-tests:camera-testlib-extensions", "camera/integration-tests/extensionstestlib", [BuildType.MAIN])
 includeProject(":car:app:app", "car/app/app", [BuildType.MAIN])
+includeProject(":car:app:app-aaos", "car/app/app-aaos", [BuildType.MAIN])
 includeProject(":cardview:cardview", "cardview/cardview", [BuildType.MAIN])
 includeProject(":collection:collection", "collection/collection", [BuildType.MAIN])
 includeProject(":collection:collection-benchmark", "collection/collection-benchmark", [BuildType.MAIN])
diff --git a/slices/view/build.gradle b/slices/view/build.gradle
index 5d8e730..29aa15a 100644
--- a/slices/view/build.gradle
+++ b/slices/view/build.gradle
@@ -27,7 +27,7 @@
 dependencies {
     implementation(project(":slice-core"))
     implementation project(":appcompat:appcompat")
-    implementation("androidx.recyclerview:recyclerview:1.1.0")
+    implementation("androidx.recyclerview:recyclerview:1.2.0-beta01")
     implementation("androidx.collection:collection:1.1.0")
     api("androidx.lifecycle:lifecycle-livedata-core:2.0.0")
 
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceContent.java b/slices/view/src/main/java/androidx/slice/widget/SliceContent.java
index 6061e64..6dc5983 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceContent.java
@@ -256,7 +256,8 @@
         }
         if (actionItem == null) {
             Intent intent = new Intent();
-            PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
+            PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 
+                PendingIntent.FLAG_IMMUTABLE);
             actionItem = new SliceItem(pi, null, FORMAT_ACTION, null, null);
         }
         if (shortcutAction != null && shortcutIcon != null && actionItem != null) {
diff --git a/viewpager2/integration-tests/testapp/build.gradle b/viewpager2/integration-tests/testapp/build.gradle
index 8eae4e5..bf00bec 100644
--- a/viewpager2/integration-tests/testapp/build.gradle
+++ b/viewpager2/integration-tests/testapp/build.gradle
@@ -31,7 +31,6 @@
     id("AndroidXPlugin")
     id("com.android.application")
     id("org.jetbrains.kotlin.android")
-    id('kotlin-android-extensions')
 }
 
 dependencies {
diff --git a/webkit/webkit/src/androidTest/java/androidx/webkit/ProxyControllerTest.java b/webkit/webkit/src/androidTest/java/androidx/webkit/ProxyControllerTest.java
index 571b9c4..c5009bf 100644
--- a/webkit/webkit/src/androidTest/java/androidx/webkit/ProxyControllerTest.java
+++ b/webkit/webkit/src/androidTest/java/androidx/webkit/ProxyControllerTest.java
@@ -147,6 +147,31 @@
 
     /**
      * This test should have an equivalent in CTS when this is implemented in the framework.
+     */
+    @Test
+    public void testReverseBypass() throws Exception {
+        WebkitUtils.checkFeature(WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS);
+
+        final String contentUrl = "http://www.example.com";
+        final String bypassUrl = "www.example.com";
+        int proxyServerRequestCount = mProxyServer.getRequestCount();
+
+        // Set proxy override with reverse bypass and load content url
+        // The content url (in the bypass list) should use proxy settings.
+        setProxyOverrideSync(new ProxyConfig.Builder()
+                .addProxyRule(mProxyServer.getHostName() + ":" + mProxyServer.getPort())
+                .addBypassRule(bypassUrl)
+                .setReverseBypass(true)
+                .build());
+        mWebViewOnUiThread.loadUrl(contentUrl);
+
+        proxyServerRequestCount++;
+        assertNotNull(mProxyServer.takeRequest(WebkitUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(proxyServerRequestCount, mProxyServer.getRequestCount());
+    }
+
+    /**
+     * This test should have an equivalent in CTS when this is implemented in the framework.
      *
      * Enumerates valid patterns to check they are supported.
      */
diff --git a/webkit/webkit/src/main/java/androidx/webkit/ProxyConfig.java b/webkit/webkit/src/main/java/androidx/webkit/ProxyConfig.java
index 1b62fc9..3fc5e78 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/ProxyConfig.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/ProxyConfig.java
@@ -17,6 +17,7 @@
 package androidx.webkit;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresFeature;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.StringDef;
 
@@ -68,14 +69,17 @@
 
     private List<ProxyRule> mProxyRules;
     private List<String> mBypassRules;
+    private boolean mReverseBypass;
 
     /**
      * @hide Internal use only
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
-    public ProxyConfig(@NonNull List<ProxyRule> proxyRules, @NonNull List<String> bypassRules) {
+    public ProxyConfig(@NonNull List<ProxyRule> proxyRules, @NonNull List<String> bypassRules,
+            boolean reverseBypass) {
         mProxyRules = proxyRules;
         mBypassRules = bypassRules;
+        mReverseBypass = reverseBypass;
     }
 
     /**
@@ -106,6 +110,17 @@
     }
 
     /**
+     * @return reverseBypass
+     *
+     * TODO(laisminchillo): unhide this when we're ready to expose this
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public boolean isReverseBypass() {
+        return mReverseBypass;
+    }
+
+    /**
      * Class that holds a scheme filter and a proxy URL.
      */
     public static final class ProxyRule {
@@ -162,6 +177,7 @@
     public static final class Builder {
         private List<ProxyRule> mProxyRules;
         private List<String> mBypassRules;
+        private boolean mReverseBypass = false;
 
         /**
          * Create an empty ProxyConfig Builder.
@@ -177,6 +193,7 @@
         public Builder(@NonNull ProxyConfig proxyConfig) {
             mProxyRules = proxyConfig.getProxyRules();
             mBypassRules = proxyConfig.getBypassRules();
+            mReverseBypass = proxyConfig.isReverseBypass();
         }
 
         /**
@@ -186,7 +203,7 @@
          */
         @NonNull
         public ProxyConfig build() {
-            return new ProxyConfig(proxyRules(), bypassRules());
+            return new ProxyConfig(proxyRules(), bypassRules(), reverseBypass());
         }
 
         /**
@@ -316,6 +333,28 @@
             return addBypassRule(BYPASS_RULE_REMOVE_IMPLICIT);
         }
 
+        /**
+         * Reverse the bypass list, so only URLs in the bypass list will use these proxy settings.
+         *
+         * <p>
+         * This method should only be called if
+         * {@link WebViewFeature#isFeatureSupported(String)}
+         * returns {@code true} for {@link WebViewFeature#PROXY_OVERRIDE_REVERSE_BYPASS}.
+         *
+         * @return This Builder object
+         *
+         * TODO(laisminchillo): unhide this when we're ready to expose this
+         * @hide
+         */
+        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        @RequiresFeature(name = WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS,
+                enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
+        @NonNull
+        public Builder setReverseBypass(boolean reverseBypass) {
+            mReverseBypass = reverseBypass;
+            return this;
+        }
+
         @NonNull
         private List<ProxyRule> proxyRules() {
             return mProxyRules;
@@ -325,5 +364,9 @@
         private List<String> bypassRules() {
             return mBypassRules;
         }
+
+        private boolean reverseBypass() {
+            return mReverseBypass;
+        }
     }
 }
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
index 55916b9..1bb99540 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
@@ -93,6 +93,7 @@
             FORCE_DARK_STRATEGY,
             WEB_MESSAGE_LISTENER,
             DOCUMENT_START_SCRIPT,
+            PROXY_OVERRIDE_REVERSE_BYPASS,
     })
     @Retention(RetentionPolicy.SOURCE)
     @Target({ElementType.PARAMETER, ElementType.METHOD})
@@ -454,6 +455,16 @@
     public static final String DOCUMENT_START_SCRIPT = "DOCUMENT_START_SCRIPT";
 
     /**
+     * Feature for {@link #isFeatureSupported(String)}.
+     * This feature covers {@link androidx.webkit.ProxyConfig.Builder.setReverseBypass(boolean)}
+     *
+     * TODO(laisminchillo): unhide when ready.
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public static final String PROXY_OVERRIDE_REVERSE_BYPASS = "PROXY_OVERRIDE_REVERSE_BYPASS";
+
+    /**
      * Return whether a feature is supported at run-time. On devices running Android version {@link
      * android.os.Build.VERSION_CODES#LOLLIPOP} and higher, this will check whether a feature is
      * supported, depending on the combination of the desired feature, the Android version of
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/ProxyControllerImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/ProxyControllerImpl.java
index 36b5074a..5d7174f 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/ProxyControllerImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/ProxyControllerImpl.java
@@ -36,13 +36,23 @@
     @Override
     public void setProxyOverride(@NonNull ProxyConfig proxyConfig, @NonNull Executor executor,
             @NonNull Runnable listener) {
-        WebViewFeatureInternal feature = WebViewFeatureInternal.PROXY_OVERRIDE;
-        if (feature.isSupportedByWebView()) {
-            // A 2D String array representation is required by reflection
-            String[][] proxyRuleArray = proxyRulesToStringArray(proxyConfig.getProxyRules());
-            String[] bypassRuleArray = proxyConfig.getBypassRules().toArray(new String[0]);
+        WebViewFeatureInternal proxyOverride = WebViewFeatureInternal.PROXY_OVERRIDE;
+        WebViewFeatureInternal reverseBypass = WebViewFeatureInternal.PROXY_OVERRIDE_REVERSE_BYPASS;
+
+        // A 2D String array representation is required by reflection
+        String[][] proxyRuleArray = proxyRulesToStringArray(proxyConfig.getProxyRules());
+        String[] bypassRuleArray = proxyConfig.getBypassRules().toArray(new String[0]);
+
+        if (proxyOverride.isSupportedByWebView() && !proxyConfig.isReverseBypass()) {
             getBoundaryInterface().setProxyOverride(
                     proxyRuleArray, bypassRuleArray, listener, executor);
+        } else if (proxyOverride.isSupportedByWebView() && reverseBypass.isSupportedByWebView()) {
+            getBoundaryInterface().setProxyOverride(
+                    proxyRuleArray,
+                    bypassRuleArray,
+                    listener,
+                    executor,
+                    proxyConfig.isReverseBypass());
         } else {
             throw WebViewFeatureInternal.getUnsupportedOperationException();
         }
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
index 2bec18d..7ff7120 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
@@ -402,6 +402,12 @@
      */
     DOCUMENT_START_SCRIPT(WebViewFeature.DOCUMENT_START_SCRIPT, Features.DOCUMENT_START_SCRIPT),
 
+    /**
+     * This feature covers {@link androidx.webkit.ProxyConfig.Builder.setReverseBypass(boolean)}
+     */
+    PROXY_OVERRIDE_REVERSE_BYPASS(WebViewFeature.PROXY_OVERRIDE_REVERSE_BYPASS,
+            Features.PROXY_OVERRIDE_REVERSE_BYPASS),
+
     ;  // This semicolon ends the enum. Add new features with a trailing comma above this line.
 
     private static final int NOT_SUPPORTED_BY_FRAMEWORK = -1;
diff --git a/window/window/src/androidTest/java/androidx/window/SidecarAdapterTest.java b/window/window/src/androidTest/java/androidx/window/SidecarAdapterTest.java
index 8bc1ba3..11ad72a 100644
--- a/window/window/src/androidTest/java/androidx/window/SidecarAdapterTest.java
+++ b/window/window/src/androidTest/java/androidx/window/SidecarAdapterTest.java
@@ -142,8 +142,8 @@
         assertTrue(actual.getDisplayFeatures().isEmpty());
     }
 
-
-    @Test
+    // TODO(b/175507310): Reinstate after fix.
+    // @Test
     @Override
     public void testTranslateWindowLayoutInfo_filterRemovesHingeFeatureNotSpanningFullDimension() {
         List<SidecarDisplayFeature> sidecarDisplayFeatures = new ArrayList<>();
@@ -167,7 +167,8 @@
         assertTrue(actual.getDisplayFeatures().isEmpty());
     }
 
-    @Test
+    // TODO(b/175507310): Reinstate after fix.
+    // @Test
     @Override
     public void testTranslateWindowLayoutInfo_filterRemovesFoldFeatureNotSpanningFullDimension() {
         List<SidecarDisplayFeature> extensionDisplayFeatures = new ArrayList<>();
diff --git a/window/window/src/main/java/androidx/window/SidecarAdapter.java b/window/window/src/main/java/androidx/window/SidecarAdapter.java
index 439921e..c245f31 100644
--- a/window/window/src/main/java/androidx/window/SidecarAdapter.java
+++ b/window/window/src/main/java/androidx/window/SidecarAdapter.java
@@ -215,6 +215,7 @@
      * with the value passed from extension.
      */
     @Nullable
+    @SuppressWarnings("UnusedVariable") // TODO(b/175507310): Remove after fix.
     private static DisplayFeature translate(SidecarDisplayFeature feature,
             SidecarDeviceState deviceState, Rect windowBounds) {
         Rect bounds = feature.getRect();
@@ -238,8 +239,9 @@
         }
         if (feature.getType() == SidecarDisplayFeature.TYPE_HINGE
                 || feature.getType() == SidecarDisplayFeature.TYPE_FOLD) {
-            if (!((bounds.left == 0 && bounds.right == windowBounds.width())
-                    || (bounds.top == 0 && bounds.bottom == windowBounds.height()))) {
+            // TODO(b/175507310): Reinstate after fix on the OEM side.
+            if (!((bounds.left == 0/* && bounds.right == windowBounds.width()*/)
+                    || (bounds.top == 0/* && bounds.bottom == windowBounds.height()*/))) {
                 // Bounds for fold and hinge types are expected to span the entire window space.
                 // See DisplayFeature#getBounds().
                 if (DEBUG) {