[go: nahoru, domu]

Merge "Extensions-interface client version stays in 1.3.0 until 1.4.0 features are completed" into androidx-main
diff --git a/appactions/interaction/interaction-capabilities-safety/build.gradle b/appactions/interaction/interaction-capabilities-safety/build.gradle
index 01b68de6..4e96499 100644
--- a/appactions/interaction/interaction-capabilities-safety/build.gradle
+++ b/appactions/interaction/interaction-capabilities-safety/build.gradle
@@ -26,7 +26,6 @@
     api(libs.autoValueAnnotations)
     api(libs.kotlinStdlib)
     annotationProcessor(libs.autoValue)
-    implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.10")
     implementation("androidx.annotation:annotation:1.1.0")
     implementation(project(":appactions:interaction:interaction-capabilities-core"))
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
index 9bde532..a140da5 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
@@ -123,6 +123,28 @@
         _binding = null
     }
 
+    private fun updateUi(advertiserUiState: AdvertiserUiState) {
+        val isAdvertising = advertiserUiState.isAdvertising
+
+        if (isAdvertising) {
+            binding.buttonAdvertise.text = getString(R.string.stop_advertising)
+            binding.buttonAdvertise.backgroundTintList = getColor(R.color.red_500)
+        } else {
+            binding.buttonAdvertise.text = getString(R.string.start_advertising)
+            binding.buttonAdvertise.backgroundTintList = getColor(R.color.indigo_500)
+        }
+        binding.checkBoxIncludeDeviceName.isEnabled = !isAdvertising
+        binding.checkBoxConnectable.isEnabled = !isAdvertising
+        binding.checkBoxDiscoverable.isEnabled = !isAdvertising
+        binding.buttonAddData.isEnabled = !isAdvertising
+        binding.viewRecyclerViewOverlay.isVisible = isAdvertising
+
+        advertiserUiState.resultMessage?.let {
+            toast(it).show()
+            viewModel.resultMessageShown()
+        }
+    }
+
     private fun initData() {
         if (ContextCompat.checkSelfPermission(
                 requireContext(),
@@ -226,26 +248,4 @@
         advertiseDataAdapter?.advertiseData = viewModel.advertiseData
         advertiseDataAdapter?.notifyItemRemoved(index)
     }
-
-    private fun updateUi(advertiserUiState: AdvertiserUiState) {
-        val isAdvertising = advertiserUiState.isAdvertising
-
-        if (isAdvertising) {
-            binding.buttonAdvertise.text = getString(R.string.stop_advertising)
-            binding.buttonAdvertise.backgroundTintList = getColor(R.color.red_500)
-        } else {
-            binding.buttonAdvertise.text = getString(R.string.start_advertising)
-            binding.buttonAdvertise.backgroundTintList = getColor(R.color.indigo_500)
-        }
-        binding.checkBoxIncludeDeviceName.isEnabled = !isAdvertising
-        binding.checkBoxConnectable.isEnabled = !isAdvertising
-        binding.checkBoxDiscoverable.isEnabled = !isAdvertising
-        binding.buttonAddData.isEnabled = !isAdvertising
-        binding.viewRecyclerViewOverlay.isVisible = isAdvertising
-
-        advertiserUiState.resultMessage?.let {
-            toast(it).show()
-            viewModel.resultMessageShown()
-        }
-    }
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt
index 910a5ab..16a8847 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt
@@ -102,7 +102,7 @@
         advertiseJob = viewModelScope.launch {
             Log.d(TAG, "bluetoothLe.advertise() called with: advertiseParams = $advertiseParams")
             _uiState.update {
-                it.copy(isAdvertising = true, resultMessage = null)
+                it.copy(isAdvertising = true)
             }
 
             bluetoothLe.advertise(advertiseParams) {
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerFragment.kt
index 067ee68..c47dc4b 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerFragment.kt
@@ -24,9 +24,7 @@
 import android.widget.CheckBox
 import android.widget.EditText
 import androidx.appcompat.app.AlertDialog
-import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.GattCharacteristic
-import androidx.bluetooth.GattServerRequest
 import androidx.bluetooth.GattService
 import androidx.bluetooth.integration.testapp.R
 import androidx.bluetooth.integration.testapp.databinding.FragmentGattServerBinding
@@ -35,14 +33,12 @@
 import androidx.bluetooth.integration.testapp.ui.common.toast
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 import dagger.hilt.android.AndroidEntryPoint
 import java.util.UUID
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
 
 @AndroidEntryPoint
@@ -52,28 +48,8 @@
         private const val TAG = "GattServerFragment"
     }
 
-    @Inject
-    lateinit var bluetoothLe: BluetoothLe
-
-    private val gattServerScope = CoroutineScope(Dispatchers.Main + Job())
-    private var gattServerJob: Job? = null
-
     private var gattServerServicesAdapter: GattServerServicesAdapter? = null
 
-    private var isGattServerOpen: Boolean = false
-        set(value) {
-            field = value
-            if (value) {
-                _binding?.buttonGattServer?.text = getString(R.string.stop_gatt_server)
-                _binding?.buttonGattServer?.backgroundTintList = getColor(R.color.red_500)
-            } else {
-                _binding?.buttonGattServer?.text = getString(R.string.open_gatt_server)
-                _binding?.buttonGattServer?.backgroundTintList = getColor(R.color.indigo_500)
-                gattServerJob?.cancel()
-                gattServerJob = null
-            }
-        }
-
     private val viewModel: GattServerViewModel by viewModels()
 
     private var _binding: FragmentGattServerBinding? = null
@@ -106,17 +82,22 @@
         )
 
         binding.buttonGattServer.setOnClickListener {
-            if (gattServerJob?.isActive == true) {
-                isGattServerOpen = false
+            if (viewModel.gattServerJob?.isActive == true) {
+                viewModel.gattServerJob?.cancel()
             } else {
-                openGattServer()
+                viewModel.openGattServer()
             }
         }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+            viewModel.uiState
+                .flowWithLifecycle(viewLifecycleOwner.lifecycle)
+                .collect(::updateUi)
+        }
     }
 
     override fun onDestroyView() {
         super.onDestroyView()
-        isGattServerOpen = false
         _binding = null
     }
 
@@ -226,82 +207,21 @@
             .show()
     }
 
-    private fun openGattServer() {
-        Log.d(TAG, "openGattServer() called")
+    private fun updateUi(gattServerUiState: GattServerUiState) {
+        val isGattServerOpen = gattServerUiState.isGattServerOpen
 
-        gattServerJob = gattServerScope.launch {
-            Log.d(
-                TAG, "bluetoothLe.openGattServer() called with: " +
-                    "viewModel.gattServerServices = ${viewModel.gattServerServices}"
-            )
-            isGattServerOpen = true
+        if (isGattServerOpen) {
+            binding.buttonGattServer.text = getString(R.string.stop_gatt_server)
+            binding.buttonGattServer.backgroundTintList = getColor(R.color.red_500)
+        } else {
+            binding.buttonGattServer.text = getString(R.string.open_gatt_server)
+            binding.buttonGattServer.backgroundTintList = getColor(R.color.indigo_500)
+        }
 
-            bluetoothLe.openGattServer(viewModel.gattServerServices) {
-                Log.d(
-                    TAG, "bluetoothLe.openGattServer() called with: " +
-                        "viewModel.gattServerServices = ${viewModel.gattServerServices}"
-                )
-
-                connectRequests.collect {
-                    Log.d(TAG, "connectRequests.collected: GattServerConnectRequest = $it")
-
-                    launch {
-                        it.accept {
-                            Log.d(
-                                TAG, "GattServerConnectRequest accepted: " +
-                                    "GattServerSessionScope = $it"
-                            )
-
-                            requests.collect { gattServerRequest ->
-                                Log.d(
-                                    TAG, "requests collected: " +
-                                        "gattServerRequest = $gattServerRequest"
-                                )
-
-                                // TODO(b/269390098): Handle requests correctly
-                                when (gattServerRequest) {
-                                    is GattServerRequest.ReadCharacteristic -> {
-                                        val characteristic = gattServerRequest.characteristic
-
-                                        val value = viewModel.readGattCharacteristicValue(
-                                            characteristic
-                                        )
-
-                                        toast(
-                                            "Read value: ${value.decodeToString()} " +
-                                                "for characteristic = ${characteristic.uuid}"
-                                        ).show()
-
-                                        gattServerRequest.sendResponse(value)
-                                    }
-
-                                    is GattServerRequest.WriteCharacteristics -> {
-                                        val characteristic =
-                                            gattServerRequest.parts[0].characteristic
-                                        val value = gattServerRequest.parts[0].value
-
-                                        toast(
-                                            "Writing value: ${value.decodeToString()} " +
-                                                "to characteristic = ${characteristic.uuid}"
-                                        ).show()
-
-                                        viewModel.updateGattCharacteristicValue(
-                                            characteristic,
-                                            value
-                                        )
-
-                                        gattServerRequest.sendResponse()
-                                    }
-
-                                    else -> {
-                                        throw NotImplementedError("Unknown request")
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
+        // TODO(ofy) If we want these to always show, we may have to pass over to mainViewModel
+        gattServerUiState.resultMessage?.let {
+            toast(it).show()
+            viewModel.resultMessageShown()
         }
     }
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerUiState.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerUiState.kt
new file mode 100644
index 0000000..ae010a3
--- /dev/null
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerUiState.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2023 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.bluetooth.integration.testapp.ui.gatt_server
+
+data class GattServerUiState(
+    val isGattServerOpen: Boolean = false,
+    val resultMessage: String? = null
+)
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerViewModel.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerViewModel.kt
index 35e1e67..6d06ac8 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerViewModel.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/gatt_server/GattServerViewModel.kt
@@ -16,22 +16,42 @@
 
 package androidx.bluetooth.integration.testapp.ui.gatt_server
 
+import android.util.Log
+import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.GattCharacteristic
+import androidx.bluetooth.GattServerRequest
 import androidx.bluetooth.GattService
 import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
 
-class GattServerViewModel : ViewModel() {
+@HiltViewModel
+class GattServerViewModel @Inject constructor(
+    private val bluetoothLe: BluetoothLe
+) : ViewModel() {
 
     private companion object {
         private const val TAG = "GattServerViewModel"
     }
 
+    var gattServerJob: Job? = null
+
     private val _gattServerServices = mutableListOf<GattService>()
     val gattServerServices: List<GattService> = _gattServerServices
 
     private val gattServerServicesCharacteristicValueMap =
         mutableMapOf<GattCharacteristic, ByteArray>()
 
+    private val _uiState = MutableStateFlow(GattServerUiState())
+    val uiState: StateFlow<GattServerUiState> = _uiState.asStateFlow()
+
     fun addGattService(gattService: GattService) {
         _gattServerServices.add(gattService)
     }
@@ -46,11 +66,107 @@
         )
     }
 
-    fun readGattCharacteristicValue(characteristic: GattCharacteristic): ByteArray {
+    fun openGattServer() {
+        Log.d(TAG, "openGattServer() called")
+
+        gattServerJob = viewModelScope.launch {
+            Log.d(
+                TAG, "bluetoothLe.openGattServer() called with " +
+                    "gattServerServices = $gattServerServices"
+            )
+            _uiState.update {
+                it.copy(isGattServerOpen = true)
+            }
+
+            bluetoothLe.openGattServer(gattServerServices) {
+                Log.d(
+                    TAG, "bluetoothLe.openGattServer() called with: " +
+                        "gattServerServices = $gattServerServices"
+                )
+
+                connectRequests.collect {
+                    Log.d(TAG, "connectRequests.collected: GattServerConnectRequest = $it")
+
+                    launch {
+                        it.accept {
+                            Log.d(
+                                TAG,
+                                "GattServerConnectRequest accepted: GattServerSessionScope = $it"
+                            )
+
+                            requests.collect { gattServerRequest ->
+                                Log.d(
+                                    TAG,
+                                    "requests collected: gattServerRequest = $gattServerRequest"
+                                )
+
+                                // TODO(b/269390098): Handle requests correctly
+                                when (gattServerRequest) {
+                                    is GattServerRequest.ReadCharacteristic -> {
+                                        val characteristic = gattServerRequest.characteristic
+                                        val value = readGattCharacteristicValue(characteristic)
+
+                                        _uiState.update { state ->
+                                            state.copy(
+                                                resultMessage = "Read value: " +
+                                                    "${value.decodeToString()} for characteristic" +
+                                                    " = ${characteristic.uuid}"
+                                            )
+                                        }
+
+                                        gattServerRequest.sendResponse(value)
+                                    }
+
+                                    is GattServerRequest.WriteCharacteristics -> {
+                                        val characteristic =
+                                            gattServerRequest.parts[0].characteristic
+                                        val value = gattServerRequest.parts[0].value
+
+                                        _uiState.update { state ->
+                                            state.copy(
+                                                resultMessage = "Writing value: " +
+                                                    "${value.decodeToString()} to characteristic" +
+                                                    " = ${characteristic.uuid}"
+                                            )
+                                        }
+
+                                        updateGattCharacteristicValue(characteristic, value)
+                                        gattServerRequest.sendResponse()
+                                    }
+
+                                    else -> {
+                                        throw NotImplementedError("Unknown request")
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        gattServerJob?.invokeOnCompletion {
+            Log.d(TAG, "bluetoothLe.openGattServer completed")
+            _uiState.update {
+                it.copy(isGattServerOpen = false)
+            }
+        }
+    }
+
+    fun resultMessageShown() {
+        _uiState.update {
+            it.copy(resultMessage = null)
+        }
+    }
+
+    private fun readGattCharacteristicValue(characteristic: GattCharacteristic): ByteArray {
         return gattServerServicesCharacteristicValueMap[characteristic] ?: ByteArray(0)
     }
 
-    fun updateGattCharacteristicValue(characteristic: GattCharacteristic, value: ByteArray) {
+    private fun updateGattCharacteristicValue(
+        characteristic: GattCharacteristic,
+        value: ByteArray
+    ) {
         gattServerServicesCharacteristicValueMap[characteristic] = value
     }
 }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/Release.kt b/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
index ec02d35..4d2aec4 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
@@ -121,20 +121,17 @@
 object Release {
     @Suppress("MemberVisibilityCanBePrivate")
     const val PROJECT_ARCHIVE_ZIP_TASK_NAME = "createProjectZip"
-    const val DIFF_TASK_PREFIX = "createDiffArchive"
     const val FULL_ARCHIVE_TASK_NAME = "createArchive"
     const val ALL_ARCHIVES_TASK_NAME = "createAllArchives"
     const val DEFAULT_PUBLISH_CONFIG = "release"
-    const val GROUP_ZIPS_FOLDER = "per-group-zips"
     const val PROJECT_ZIPS_FOLDER = "per-project-zips"
-    const val GROUP_ZIP_PREFIX = "gmaven"
     const val GLOBAL_ZIP_PREFIX = "top-of-tree-m2repository"
 
     // lazily created config action params so that we don't keep re-creating them
     private var configActionParams: GMavenZipTask.ConfigAction.Params? = null
 
     /**
-     * Registers the project to be included in its group's zip file as well as the global zip files.
+     * Registers the project to be included in the global zip file.
      */
     fun register(project: Project, extension: AndroidXExtension) {
         if (!extension.shouldPublish()) {
@@ -159,11 +156,11 @@
             return
         }
 
-        val mavenGroup =
-            extension.mavenGroup?.group
-                ?: throw IllegalArgumentException(
-                    "Cannot register a project to release if it does not have a mavenGroup set up"
-                )
+        if (extension.mavenGroup?.group == null) {
+            throw IllegalArgumentException(
+                "Cannot register a project to release if it does not have a mavenGroup set up"
+            )
+        }
         if (!extension.isVersionSet()) {
             throw IllegalArgumentException(
                 "Cannot register a project to release if it does not have a mavenVersion set up"
@@ -175,7 +172,6 @@
         val zipTasks =
             listOf(
                 projectZipTask,
-                getGroupReleaseZipTask(project, mavenGroup),
                 getGlobalFullZipTask(project)
             )
 
@@ -295,28 +291,6 @@
         )
     }
 
-    /** Creates and returns the zip task that includes artifacts only in the given maven group. */
-    private fun getGroupReleaseZipTask(
-        project: Project,
-        group: String
-    ): TaskProvider<GMavenZipTask> {
-        return project.rootProject.maybeRegister(
-            name = "${DIFF_TASK_PREFIX}For${groupToTaskNameSuffix(group)}",
-             task: GMavenZipTask ->
-                GMavenZipTask.ConfigAction(
-                        getParams(
-                            project = project,
-                            distDir = File(project.getDistributionDirectory(), GROUP_ZIPS_FOLDER),
-                            fileNamePrefix = GROUP_ZIP_PREFIX,
-                            group = group
-                        )
-                    )
-                    .execute(task)
-            },
-             taskProvider -> project.addToAnchorTask(taskProvider) }
-        )
-    }
-
     private fun getProjectZipTask(project: Project): TaskProvider<GMavenZipTask> {
         val taskProvider =
             project.tasks.register(PROJECT_ARCHIVE_ZIP_TASK_NAME, GMavenZipTask::class.java) {
@@ -510,13 +484,6 @@
         "-${project.version}.zip"
 }
 
-fun Project.getGroupZipPath(): String {
-    return Release.GROUP_ZIPS_FOLDER +
-        "/" +
-        getZipName(Release.GROUP_ZIP_PREFIX, project.group.toString()) +
-        ".zip"
-}
-
 fun Project.getGlobalZipFile(): File {
     return File(
         project.getDistributionDirectory(),
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
index 94757ef..fb83246 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
@@ -19,7 +19,6 @@
 import androidx.build.AndroidXExtension
 import androidx.build.LibraryGroup
 import androidx.build.getBuildInfoDirectory
-import androidx.build.getGroupZipPath
 import androidx.build.getProjectZipPath
 import androidx.build.getSupportRootFolder
 import androidx.build.gitclient.getHeadShaProvider
@@ -90,8 +89,6 @@
 
     @get:Input abstract val groupIdRequiresSameVersion: Property<Boolean>
 
-    @get:Input abstract val groupZipPath: Property<String>
-
     @get:Input abstract val projectZipPath: Property<String>
 
     @get:[Input Optional]
@@ -131,7 +128,6 @@
         libraryBuildInfoFile.path = projectDir.get()
         libraryBuildInfoFile.sha = commit.get()
         libraryBuildInfoFile.groupIdRequiresSameVersion = groupIdRequiresSameVersion.get()
-        libraryBuildInfoFile.groupZipPath = groupZipPath.get()
         libraryBuildInfoFile.projectZipPath = projectZipPath.get()
         libraryBuildInfoFile.kotlinVersion = kotlinVersion.orNull
         libraryBuildInfoFile.checks = ArrayList()
@@ -184,7 +180,6 @@
                 )
                 task.commit.set(shaProvider)
                 task.groupIdRequiresSameVersion.set(mavenGroup?.requireSameVersion ?: false)
-                task.groupZipPath.set(project.getGroupZipPath())
                 task.projectZipPath.set(project.getProjectZipPath())
 
                 // Note:
diff --git a/camera/camera-video/api/current.txt b/camera/camera-video/api/current.txt
index bf615af..df297e5 100644
--- a/camera/camera-video/api/current.txt
+++ b/camera/camera-video/api/current.txt
@@ -113,11 +113,15 @@
     method public androidx.camera.video.QualitySelector getQualitySelector();
     method public int getTargetVideoEncodingBitRate();
     method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo);
+    method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo, int);
+    method public int getVideoCapabilitiesSource();
     method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
     method @RequiresApi(26) public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileDescriptorOutputOptions);
     method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileOutputOptions);
     method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.MediaStoreOutputOptions);
     field public static final androidx.camera.video.QualitySelector DEFAULT_QUALITY_SELECTOR;
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE = 0; // 0x0
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CODEC_CAPABILITIES = 1; // 0x1
   }
 
   @RequiresApi(21) public static final class Recorder.Builder {
@@ -127,6 +131,7 @@
     method public androidx.camera.video.Recorder.Builder setExecutor(java.util.concurrent.Executor);
     method public androidx.camera.video.Recorder.Builder setQualitySelector(androidx.camera.video.QualitySelector);
     method public androidx.camera.video.Recorder.Builder setTargetVideoEncodingBitRate(@IntRange(from=1) int);
+    method public androidx.camera.video.Recorder.Builder setVideoCapabilitiesSource(int);
   }
 
   @RequiresApi(21) public final class Recording implements java.lang.AutoCloseable {
diff --git a/camera/camera-video/api/restricted_current.txt b/camera/camera-video/api/restricted_current.txt
index bf615af..df297e5 100644
--- a/camera/camera-video/api/restricted_current.txt
+++ b/camera/camera-video/api/restricted_current.txt
@@ -113,11 +113,15 @@
     method public androidx.camera.video.QualitySelector getQualitySelector();
     method public int getTargetVideoEncodingBitRate();
     method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo);
+    method public static androidx.camera.video.VideoCapabilities getVideoCapabilities(androidx.camera.core.CameraInfo, int);
+    method public int getVideoCapabilitiesSource();
     method public void onSurfaceRequested(androidx.camera.core.SurfaceRequest);
     method @RequiresApi(26) public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileDescriptorOutputOptions);
     method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.FileOutputOptions);
     method public androidx.camera.video.PendingRecording prepareRecording(android.content.Context, androidx.camera.video.MediaStoreOutputOptions);
     field public static final androidx.camera.video.QualitySelector DEFAULT_QUALITY_SELECTOR;
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE = 0; // 0x0
+    field public static final int VIDEO_CAPABILITIES_SOURCE_CODEC_CAPABILITIES = 1; // 0x1
   }
 
   @RequiresApi(21) public static final class Recorder.Builder {
@@ -127,6 +131,7 @@
     method public androidx.camera.video.Recorder.Builder setExecutor(java.util.concurrent.Executor);
     method public androidx.camera.video.Recorder.Builder setQualitySelector(androidx.camera.video.QualitySelector);
     method public androidx.camera.video.Recorder.Builder setTargetVideoEncodingBitRate(@IntRange(from=1) int);
+    method public androidx.camera.video.Recorder.Builder setVideoCapabilitiesSource(int);
   }
 
   @RequiresApi(21) public final class Recording implements java.lang.AutoCloseable {
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java b/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
index 6c9a3f2..f05dfd2 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
@@ -175,7 +175,7 @@
     private static final String TAG = "Recorder";
 
     /**
-     * Video capabilities refers to {@link CamcorderProfile}.
+     * Video capabilities are derived from {@link CamcorderProfile}.
      *
      * <p>The {@link Quality} supported by the video capabilities of this source are determined by
      * the device's {@link CamcorderProfile}. This means that the quality of recorded videos is
@@ -184,24 +184,21 @@
      *
      * @see Builder#setVideoCapabilitiesSource(int)
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY) // TODO(b/263961771): make API public
     public static final int VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE = 0;
 
     /**
-     * Video capabilities refers to codec capabilities.
+     * Video capabilities are derived from codec capabilities.
      *
      * <p>The {@link Quality} supported by the video capabilities of this source are determined by
-     * the codec capabilities, including the {@link Quality} supported by the
-     * {@link CamcorderProfile}. However, the quality of recorded videos for those
-     * {@link Quality} supported beyond {@link CamcorderProfile} is not guaranteed. Therefore, it is
-     * recommended to use {@link #VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE} unless there is a
-     * specific reason. A common use case is when the application strives to record UHD video
-     * whenever feasible, but the device's {@link CamcorderProfile} does not include a UHD quality
-     * setting, even though the codec is capable of recording UHD video.
+     * the codec capabilities. However, the recorded videos is not guaranteed. For example, there
+     * may be frame drops due to thermal throttling or memory pressure.
+     * Therefore, it is recommended to use {@link #VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE}
+     * unless there is a specific reason. A common use case is when the application strives to
+     * record UHD video whenever feasible, but the device's {@link CamcorderProfile} does not
+     * include a UHD quality setting, even though the codec is capable of recording UHD video.
      *
      * @see Builder#setVideoCapabilitiesSource(int)
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY) // TODO(b/263961771): make API public
     public static final int VIDEO_CAPABILITIES_SOURCE_CODEC_CAPABILITIES = 1;
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -673,7 +670,6 @@
      * used to create this recorder, or the default value
      * {@link #VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE} if not set.
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY) // TODO(b/263961771): make API public
     @VideoCapabilitiesSource
     public int getVideoCapabilitiesSource() {
         return mVideoCapabilitiesSource;
@@ -2813,6 +2809,10 @@
      * qualities. This information can be used for things like checking if HDR is supported for
      * configuring VideoCapture to record HDR video.
      *
+     * <p>The source of the returned {@link VideoCapabilities} is
+     * {@link #VIDEO_CAPABILITIES_SOURCE_CAMCORDER_PROFILE}. To get a {@link VideoCapabilities}
+     * from a different source, use {@link Recorder#getVideoCapabilities(CameraInfo, int)}.
+     *
      * @param cameraInfo info about the camera.
      * @return VideoCapabilities with respect to the input camera info.
      */
@@ -2838,7 +2838,6 @@
      * @return VideoCapabilities with respect to the input camera info and video capabilities
      * source.
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY) // TODO(b/263961771): make API public
     @NonNull
     public static VideoCapabilities getVideoCapabilities(@NonNull CameraInfo cameraInfo,
             @VideoCapabilitiesSource int videoCapabilitiesSource) {
@@ -3353,7 +3352,6 @@
          * @throws IllegalArgumentException if videoCapabilitiesSource is not one of the possible
          * values.
          */
-        @RestrictTo(RestrictTo.Scope.LIBRARY) // TODO(b/263961771): make API public
         @NonNull
         public Builder setVideoCapabilitiesSource(
                 @VideoCapabilitiesSource int videoCapabilitiesSource) {
diff --git a/compose/foundation/foundation-layout/src/androidMain/kotlin/androidx/compose/foundation/layout/WindowInsets.android.kt b/compose/foundation/foundation-layout/src/androidMain/kotlin/androidx/compose/foundation/layout/WindowInsets.android.kt
index ed81e0f..4ebb005 100644
--- a/compose/foundation/foundation-layout/src/androidMain/kotlin/androidx/compose/foundation/layout/WindowInsets.android.kt
+++ b/compose/foundation/foundation-layout/src/androidMain/kotlin/androidx/compose/foundation/layout/WindowInsets.android.kt
@@ -119,6 +119,22 @@
     }
 
 /**
+ * Indicates whether access to [WindowInsets] within the [content][ComposeView.setContent]
+ * should consume the Android  [android.view.WindowInsets]. The default value is `true`, meaning
+ * that access to [WindowInsets.Companion] will consume the Android WindowInsets.
+ *
+ * This property should be set prior to first composition.
+ */
+@Deprecated(
+    level = DeprecationLevel.HIDDEN,
+    message = "Please use AbstractComposeView.consumeWindowInsets")
+var ComposeView.consumeWindowInsets: Boolean
+    get() = getTag(R.id.consume_window_insets_tag) as? Boolean ?: true
+    set(value) {
+        setTag(R.id.consume_window_insets_tag, value)
+    }
+
+/**
  * For the [WindowInsetsCompat.Type.captionBar].
  */
 actual val WindowInsets.Companion.captionBar: WindowInsets
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/OWNERS b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/OWNERS
new file mode 100644
index 0000000..f897dda5
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 630734
+include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text2/OWNERS b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text2/OWNERS
new file mode 100644
index 0000000..f897dda5
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text2/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 630734
+include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/OWNERS b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/OWNERS
new file mode 100644
index 0000000..f897dda5
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 630734
+include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldCursorTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldCursorTest.kt
index 38a96aa..1971592 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldCursorTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldCursorTest.kt
@@ -575,6 +575,7 @@
             )
     }
 
+    @Ignore("b/308895081")
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun cursorNotBlinking_whenWindowLostFocus() {
@@ -617,6 +618,7 @@
             .assertDoesNotContainColor(cursorColor)
     }
 
+    @Ignore("b/308895081")
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun focusedTextField_resumeBlinking_whenWindowRegainsFocus() {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldSelectionTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldSelectionTest.kt
index 68ec6e1..356477b 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldSelectionTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/textfield/TextFieldSelectionTest.kt
@@ -204,6 +204,7 @@
         )
     }
 
+    @Ignore("b/308895081")
     @Test
     fun textField_noSelectionHandles_whenWindowLosesFocus() {
         val textFieldValue = mutableStateOf(TextFieldValue("texttexttext"))
@@ -246,6 +247,7 @@
         assertHandlesNotExist()
     }
 
+    @Ignore("b/308895081")
     @Test
     fun textField_redisplaysSelectionHandlesAndToolbar_whenWindowRegainsFocus() {
         val textFieldValue = mutableStateOf(TextFieldValue("texttexttext"))
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/OWNERS b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/OWNERS
new file mode 100644
index 0000000..f897dda5
--- /dev/null
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 630734
+include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text2/OWNERS b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text2/OWNERS
new file mode 100644
index 0000000..f897dda5
--- /dev/null
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text2/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 630734
+include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
index d7c2838..b56c733 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
@@ -86,6 +86,7 @@
 import androidx.compose.ui.platform.LocalTextToolbar
 import androidx.compose.ui.platform.LocalWindowInfo
 import androidx.compose.ui.platform.SoftwareKeyboardController
+import androidx.compose.ui.platform.WindowInfo
 import androidx.compose.ui.semantics.copyText
 import androidx.compose.ui.semantics.cutText
 import androidx.compose.ui.semantics.disabled
@@ -416,7 +417,7 @@
         state.layoutResult?.innerTextFieldCoordinates = it
         if (enabled) {
             if (state.handleState == HandleState.Selection) {
-                if (state.showFloatingToolbar && windowInfo.isWindowFocused) {
+                if (state.showFloatingToolbar && isWindowFocusedBehindFlag(windowInfo)) {
                     manager.showSelectionToolbar()
                 } else {
                     manager.hideSelectionToolbar()
@@ -582,7 +583,7 @@
         }
     }
 
-    val showCursor = enabled && !readOnly && windowInfo.isWindowFocused
+    val showCursor = enabled && !readOnly && isWindowFocusedBehindFlag(windowInfo)
     val cursorModifier = Modifier.cursor(state, value, offsetMapping, cursorBrush, showCursor)
 
     DisposableEffect(manager) {
@@ -631,7 +632,7 @@
         }
 
     val showHandleAndMagnifier =
-        enabled && state.hasFocus && state.isInTouchMode && windowInfo.isWindowFocused
+        enabled && state.hasFocus && state.isInTouchMode && isWindowFocusedBehindFlag(windowInfo)
     val magnifierModifier = if (showHandleAndMagnifier) {
         Modifier.textFieldMagnifier(manager)
     } else {
@@ -1185,3 +1186,8 @@
         )
     }
 }
+
+// (b/308895081) Temporary disable use of Window Focus for cursor blinking state
+internal const val USE_WINDOW_FOCUS_ENABLED = false
+internal fun isWindowFocusedBehindFlag(windowInfo: WindowInfo) =
+    if (USE_WINDOW_FOCUS_ENABLED) windowInfo.isWindowFocused else true
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/OWNERS b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/OWNERS
new file mode 100644
index 0000000..f897dda5
--- /dev/null
+++ b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/text/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 630734
+include /TEXT_OWNERS
\ No newline at end of file
diff --git a/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/anchoredDraggable/AnchoredDraggableGestureTest.kt b/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/anchoredDraggable/AnchoredDraggableGestureTest.kt
index ae56214..ced2446 100644
--- a/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/anchoredDraggable/AnchoredDraggableGestureTest.kt
+++ b/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/anchoredDraggable/AnchoredDraggableGestureTest.kt
@@ -913,6 +913,66 @@
         assertThat(state.targetValue).isEqualTo(B) // B is the closest now so we should target it
     }
 
+    @Test
+    fun anchoredDraggable_animationNotCancelledByDrag_startDragImmediatelyIsFalse() {
+        rule.mainClock.autoAdvance = false
+        val anchors = DraggableAnchors {
+            A at 0f
+            B at 250f
+            C at 500f
+        }
+        val state = AnchoredDraggableState(
+            initialValue = A,
+            positionalThreshold = { totalDistance -> totalDistance * 0.5f },
+            velocityThreshold = DefaultVelocityThreshold,
+            animationSpec = tween(),
+            anchors = anchors
+        )
+        lateinit var scope: CoroutineScope
+        rule.setContent {
+            WithTouchSlop(touchSlop = 0f) {
+                scope = rememberCoroutineScope()
+                Box(Modifier.fillMaxSize()) {
+                    Box(
+                        Modifier
+                            .requiredSize(AnchoredDraggableBoxSize)
+                            .testTag(AnchoredDraggableTestTag)
+                            .anchoredDraggable(
+                                state = state,
+                                orientation = Orientation.Horizontal,
+                                startDragImmediately = false,
+                            )
+                            .offset {
+                                IntOffset(
+                                    state
+                                        .requireOffset()
+                                        .roundToInt(), 0
+                                )
+                            }
+                            .background(Color.Red)
+                    )
+                }
+            }
+        }
+        assertThat(state.currentValue).isEqualTo(A)
+        assertThat(state.targetValue).isEqualTo(A)
+
+        scope.launch { state.animateTo(C) }
+
+        rule.mainClock.advanceTimeUntil {
+            state.requireOffset() > abs(state.requireOffset() - anchors.positionOf(B))
+        } // Advance until our closest anchor is B
+        assertThat(state.targetValue).isEqualTo(C)
+
+        rule.onNodeWithTag(AnchoredDraggableTestTag)
+            .performTouchInput {
+                down(Offset.Zero)
+            }
+        rule.waitForIdle()
+
+        assertThat(state.targetValue).isEqualTo(C) // Animation will continue to C
+    }
+
     private val DefaultPositionalThreshold: (totalDistance: Float) -> Float = {
         with(rule.density) { 56.dp.toPx() }
     }
diff --git a/compose/material/material/src/androidMain/kotlin/androidx/compose/material/internal/ExposedDropdownMenuPopup.android.kt b/compose/material/material/src/androidMain/kotlin/androidx/compose/material/internal/ExposedDropdownMenuPopup.android.kt
index e810b09..15a7bf7 100644
--- a/compose/material/material/src/androidMain/kotlin/androidx/compose/material/internal/ExposedDropdownMenuPopup.android.kt
+++ b/compose/material/material/src/androidMain/kotlin/androidx/compose/material/internal/ExposedDropdownMenuPopup.android.kt
@@ -28,6 +28,7 @@
 import android.view.ViewOutlineProvider
 import android.view.ViewTreeObserver
 import android.view.WindowManager
+import android.view.accessibility.AccessibilityManager
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionContext
 import androidx.compose.runtime.DisposableEffect
@@ -44,12 +45,13 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.R
 import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.toComposeIntRect
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.layout.positionInWindow
 import androidx.compose.ui.platform.AbstractComposeView
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.LocalView
@@ -86,17 +88,22 @@
     val density = LocalDensity.current
     val testTag = LocalPopupTestTag.current
     val layoutDirection = LocalLayoutDirection.current
+    val context = LocalContext.current
+    val a11yManager =
+        context.getSystemService(Context.ACCESSIBILITY_SERVICE) as? AccessibilityManager
+
     val parentComposition = rememberCompositionContext()
     val currentContent by rememberUpdatedState(content)
     val popupId = rememberSaveable { UUID.randomUUID() }
-    val popupLayout = remember {
+    val popupLayout = remember(a11yManager) {
         PopupLayout(
             >
             testTag = testTag,
             composeView = view,
+            focusable = a11yManager?.isTouchExplorationEnabled == true,
             density = density,
             initialPositionProvider = popupPositionProvider,
-            popupId = popupId
+            popupId = popupId,
         ).apply {
             setContent(parentComposition) {
                 SimpleStack(
@@ -215,6 +222,7 @@
     private var onDismissRequest: (() -> Unit)?,
     var testTag: String,
     private val composeView: View,
+    private val focusable: Boolean,
     density: Density,
     initialPositionProvider: PopupPositionProvider,
     popupId: UUID
@@ -246,15 +254,6 @@
 
     override val subCompositionView: AbstractComposeView get() = this
 
-    // Specific to exposed dropdown menus.
-    private val dismissOnOutsideClick = { offset: Offset?, bounds: IntRect ->
-        if (offset == null) false
-        else {
-            offset.x < bounds.left || offset.x > bounds.right ||
-                offset.y < bounds.top || offset.y > bounds.bottom
-        }
-    }
-
     init {
         id = android.R.id.content
         setViewTreeLifecycleOwner(composeView.findViewTreeLifecycleOwner())
@@ -343,10 +342,10 @@
         val parentBounds = parentBounds ?: return
         val popupContentSize = popupContentSize ?: return
 
-        val windowSize = previousWindowVisibleFrame.let {
-            composeView.getWindowVisibleDisplayFrame(it)
-            val bounds = it.toIntBounds()
-            IntSize(width = bounds.width, height = bounds.height)
+        val windowSize = previousWindowVisibleFrame.let { rect ->
+            composeView.getWindowVisibleDisplayFrame(rect)
+            val bounds = rect.toComposeIntRect()
+            bounds.size
         }
 
         val popupPosition = positionProvider.calculatePosition(
@@ -386,13 +385,11 @@
                 (event.x < 0 || event.x >= width || event.y < 0 || event.y >= height)) ||
             event.action == MotionEvent.ACTION_OUTSIDE
         ) {
-            val parentBounds = parentBounds
-            val shouldDismiss = parentBounds == null || dismissOnOutsideClick(
-                // Keep menu open if ACTION_OUTSIDE event is reported as raw coordinates of (0, 0).
-                // This means it belongs to another owner, e.g., the soft keyboard or other window.
-                if (event.rawX != 0f && event.rawY != 0f) Offset(event.rawX, event.rawY) else null,
-                parentBounds
-            )
+            // If an event has raw coordinates of (0, 0), it means it belongs to another owner,
+            // e.g., the soft keyboard or other window, so we want to keep the menu open.
+            val isOutsideClickOnKeyboard = event.rawX == 0f && event.rawY == 0f
+
+            val shouldDismiss = parentBounds == null || !isOutsideClickOnKeyboard
             if (shouldDismiss) {
                 onDismissRequest?.invoke()
                 return true
@@ -424,9 +421,15 @@
             gravity = Gravity.START or Gravity.TOP
 
             // Flags specific to exposed dropdown menu.
-            flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
-                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
+            flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH and
+                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL.inv() or
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+            flags = if (focusable) {
+                flags and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv()
+            } else {
+                flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+            }
+
             softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
 
             type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
@@ -446,13 +449,6 @@
         }
     }
 
-    private fun Rect.toIntBounds() = IntRect(
-        left = left,
-        top = top,
-        right = right,
-        bottom = bottom
-    )
-
     override fun onGlobalLayout() {
         // Update the position of the popup, in case getWindowVisibleDisplayFrame has changed.
         composeView.getWindowVisibleDisplayFrame(tmpWindowVisibleFrame)
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/AnchoredDraggable.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/AnchoredDraggable.kt
index bcdba2a..adbea67 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/AnchoredDraggable.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/AnchoredDraggable.kt
@@ -154,6 +154,9 @@
  * drag will behave like bottom to top, and a left to right drag will behave like right to left.
  * @param interactionSource Optional [MutableInteractionSource] that will passed on to
  * the internal [Modifier.draggable].
+ * @param startDragImmediately when set to false, [draggable] will start dragging only when the
+ * gesture crosses the touchSlop. This is useful to prevent users from "catching" an animating
+ * widget when pressing on it. See [draggable] to learn more about startDragImmediately.
  */
 @ExperimentalMaterialApi
 internal fun <T> Modifier.anchoredDraggable(
@@ -161,14 +164,15 @@
     orientation: Orientation,
     enabled: Boolean = true,
     reverseDirection: Boolean = false,
-    interactionSource: MutableInteractionSource? = null
+    interactionSource: MutableInteractionSource? = null,
+    startDragImmediately: Boolean = state.isAnimationRunning
 ) = draggable(
     state = state.draggableState,
     orientation = orientation,
     enabled = enabled,
     interactionSource = interactionSource,
     reverseDirection = reverseDirection,
-    startDragImmediately = state.isAnimationRunning,
+    startDragImmediately = startDragImmediately,
      velocity -> launch { state.settle(velocity) } }
 )
 
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt
index 4afd313..c3e25c4 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Switch.kt
@@ -165,7 +165,8 @@
                 orientation = Orientation.Horizontal,
                 enabled = enabled && onCheckedChange != null,
                 reverseDirection = isRtl,
-                interactionSource = interactionSource
+                interactionSource = interactionSource,
+                startDragImmediately = false
             )
             .wrapContentSize(Alignment.Center)
             .padding(DefaultSwitchPadding)
diff --git a/compose/material3/material3-common/api/current.txt b/compose/material3/material3-common/api/current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/compose/material3/material3-common/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/compose/material3/material3-common/api/res-current.txt b/compose/material3/material3-common/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/material3/material3-common/api/res-current.txt
diff --git a/compose/material3/material3-common/api/restricted_current.txt b/compose/material3/material3-common/api/restricted_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/compose/material3/material3-common/api/restricted_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/compose/material3/material3-common/build.gradle b/compose/material3/material3-common/build.gradle
new file mode 100644
index 0000000..23b5dba
--- /dev/null
+++ b/compose/material3/material3-common/build.gradle
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 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.LibraryType
+import androidx.build.PlatformIdentifier
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+    id("AndroidXPlugin")
+    id("AndroidXComposePlugin")
+    id("com.android.library")
+}
+
+androidXMultiplatform {
+    android()
+    desktop()
+
+    defaultPlatform(PlatformIdentifier.ANDROID)
+
+    sourceSets {
+        commonMain {
+            dependencies {
+                implementation(libs.kotlinStdlibCommon)
+            }
+        }
+        androidMain.dependencies {
+        }
+
+        commonTest {
+            dependencies {
+            }
+        }
+
+        jvmMain {
+            dependsOn(commonMain)
+            dependencies {
+                implementation(libs.kotlinStdlib)
+            }
+        }
+
+        androidMain {
+            dependsOn(jvmMain)
+            dependencies {
+                api("androidx.annotation:annotation:1.1.0")
+            }
+        }
+
+        desktopMain {
+            dependsOn(jvmMain)
+            dependencies {
+                implementation(libs.kotlinStdlib)
+            }
+        }
+
+        jvmTest {
+            dependsOn(commonTest)
+            dependencies {
+            }
+        }
+
+        androidInstrumentedTest {
+            dependsOn(jvmTest)
+            dependencies {
+                implementation(project(":compose:material3:material3-common"))
+                implementation(project(":compose:test-utils"))
+                implementation(libs.testRules)
+                implementation(libs.junit)
+                implementation(libs.truth)
+            }
+        }
+
+        desktopTest {
+            dependsOn(jvmTest)
+            dependencies {
+            }
+        }
+    }
+}
+
+android {
+    namespace "androidx.compose.material3.common"
+}
+
+androidx {
+    name = "Compose Material 3 Common components"
+    mavenVersion = LibraryVersions.COMPOSE_MATERIAL3_COMMON
+    type = LibraryType.PUBLISHED_LIBRARY
+    publish = Publish.NONE
+    inceptionYear = "2023"
+    description = "Compose Material 3 Common Library. This library contains foundational, themeless " +
+            "components that can be shared between different Material libraries or used by app" +
+            " developers. It builds upon the Jetpack Compose libraries."
+}
diff --git a/compose/material3/material3-common/src/commonMain/kotlin/androidx/compose/material3/androidx-compose-material3-material3-common-documentation.md b/compose/material3/material3-common/src/commonMain/kotlin/androidx/compose/material3/androidx-compose-material3-material3-common-documentation.md
new file mode 100644
index 0000000..e837788
--- /dev/null
+++ b/compose/material3/material3-common/src/commonMain/kotlin/androidx/compose/material3/androidx-compose-material3-material3-common-documentation.md
@@ -0,0 +1,8 @@
+# Module root
+
+Compose Material 3 Common
+
+# Package androidx.compose.material3.common
+
+## Overview
+
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 99338f7..2787689 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -2036,3 +2036,42 @@
 
 }
 
+package androidx.compose.material3.pulltorefresh {
+
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class PullToRefreshDefaults {
+    method @androidx.compose.runtime.Composable public void Indicator(androidx.compose.material3.pulltorefresh.PullToRefreshState state, optional androidx.compose.ui.Modifier modifier, optional long color);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method public float getPositionalThreshold();
+    method public androidx.compose.ui.graphics.Shape getShape();
+    property public final float PositionalThreshold;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    property public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.pulltorefresh.PullToRefreshDefaults INSTANCE;
+  }
+
+  public final class PullToRefreshKt {
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void PullToRefreshContainer(androidx.compose.material3.pulltorefresh.PullToRefreshState state, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.pulltorefresh.PullToRefreshState,kotlin.Unit> indicator, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static androidx.compose.material3.pulltorefresh.PullToRefreshState PullToRefreshState(float positionalThresholdPx, optional boolean initialRefreshing, optional kotlin.jvm.functions.Function0<java.lang.Boolean> enabled);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.pulltorefresh.PullToRefreshState rememberPullToRefreshState(optional float positionalThreshold, optional kotlin.jvm.functions.Function0<java.lang.Boolean> enabled);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface PullToRefreshState {
+    method public void endRefresh();
+    method public androidx.compose.ui.input.nestedscroll.NestedScrollConnection getNestedScrollConnection();
+    method public float getPositionalThreshold();
+    method @FloatRange(from=0.0) public float getProgress();
+    method @FloatRange(from=0.0) public float getVerticalOffset();
+    method public boolean isRefreshing();
+    method public void setNestedScrollConnection(androidx.compose.ui.input.nestedscroll.NestedScrollConnection);
+    method public void startRefresh();
+    property public abstract boolean isRefreshing;
+    property public abstract androidx.compose.ui.input.nestedscroll.NestedScrollConnection nestedScrollConnection;
+    property public abstract float positionalThreshold;
+    property @FloatRange(from=0.0) public abstract float progress;
+    property @FloatRange(from=0.0) public abstract float verticalOffset;
+  }
+
+}
+
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 99338f7..2787689 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -2036,3 +2036,42 @@
 
 }
 
+package androidx.compose.material3.pulltorefresh {
+
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class PullToRefreshDefaults {
+    method @androidx.compose.runtime.Composable public void Indicator(androidx.compose.material3.pulltorefresh.PullToRefreshState state, optional androidx.compose.ui.Modifier modifier, optional long color);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method public float getPositionalThreshold();
+    method public androidx.compose.ui.graphics.Shape getShape();
+    property public final float PositionalThreshold;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    property public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.pulltorefresh.PullToRefreshDefaults INSTANCE;
+  }
+
+  public final class PullToRefreshKt {
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void PullToRefreshContainer(androidx.compose.material3.pulltorefresh.PullToRefreshState state, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.pulltorefresh.PullToRefreshState,kotlin.Unit> indicator, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static androidx.compose.material3.pulltorefresh.PullToRefreshState PullToRefreshState(float positionalThresholdPx, optional boolean initialRefreshing, optional kotlin.jvm.functions.Function0<java.lang.Boolean> enabled);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.pulltorefresh.PullToRefreshState rememberPullToRefreshState(optional float positionalThreshold, optional kotlin.jvm.functions.Function0<java.lang.Boolean> enabled);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface PullToRefreshState {
+    method public void endRefresh();
+    method public androidx.compose.ui.input.nestedscroll.NestedScrollConnection getNestedScrollConnection();
+    method public float getPositionalThreshold();
+    method @FloatRange(from=0.0) public float getProgress();
+    method @FloatRange(from=0.0) public float getVerticalOffset();
+    method public boolean isRefreshing();
+    method public void setNestedScrollConnection(androidx.compose.ui.input.nestedscroll.NestedScrollConnection);
+    method public void startRefresh();
+    property public abstract boolean isRefreshing;
+    property public abstract androidx.compose.ui.input.nestedscroll.NestedScrollConnection nestedScrollConnection;
+    property public abstract float positionalThreshold;
+    property @FloatRange(from=0.0) public abstract float progress;
+    property @FloatRange(from=0.0) public abstract float verticalOffset;
+  }
+
+}
+
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
index 12a41b1..3c26f67 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
@@ -270,6 +270,19 @@
     examples = ProgressIndicatorsExamples
 )
 
+private val PullToRefreshIndicators = Component(
+    id = nextId(),
+    name = "Pull-to-Refresh Indicator",
+    description = "Pull to refresh is a swipe gesture available at the beginning of lists, grid " +
+        "lists, and card collections where the most recent content appears ",
+    // No pull-to-refresh icon
+    // TODO: Request component guidelines documentation from design.
+    guidelinesUrl = "",
+    docsUrl = "$DocsUrl#pulltorefreshcontainer",
+    sourceUrl = "$Material3SourceUrl/PullToRefresh.kt",
+    examples = PullToRefreshExamples
+)
+
 private val RadioButtons = Component(
     id = nextId(),
     name = "Radio buttons",
@@ -415,6 +428,7 @@
     NavigationRail,
     NavigationSuiteScaffold,
     ProgressIndicators,
+    PullToRefreshIndicators,
     RadioButtons,
     SearchBars,
     SegmentedButtons,
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
index c50dec9..607ff78 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
@@ -106,6 +106,8 @@
 import androidx.compose.material3.samples.PlainTooltipWithManualInvocationSample
 import androidx.compose.material3.samples.PrimaryIconTabs
 import androidx.compose.material3.samples.PrimaryTextTabs
+import androidx.compose.material3.samples.PullToRefreshSample
+import androidx.compose.material3.samples.PullToRefreshSampleCustomState
 import androidx.compose.material3.samples.RadioButtonSample
 import androidx.compose.material3.samples.RadioGroupSample
 import androidx.compose.material3.samples.RangeSliderSample
@@ -777,6 +779,25 @@
     }
 )
 
+private const val PullToRefreshExampleDescription = "Pull-to-refresh examples"
+private const val PullToRefreshExampleSourceUrl = "$SampleSourceUrl/PullToRefreshSamples.kt"
+val PullToRefreshExamples = listOf(
+    Example(
+        name = ::PullToRefreshSample.name,
+        description = PullToRefreshExampleDescription,
+        sourceUrl = PullToRefreshExampleSourceUrl
+    ) {
+        PullToRefreshSample()
+    },
+    Example(
+        name = ::PullToRefreshSampleCustomState.name,
+        description = PullToRefreshExampleDescription,
+        sourceUrl = PullToRefreshExampleSourceUrl
+    ) {
+        PullToRefreshSampleCustomState()
+    }
+)
+
 private const val RadioButtonsExampleDescription = "Radio buttons examples"
 private const val RadioButtonsExampleSourceUrl = "$SampleSourceUrl/RadioButtonSamples.kt"
 val RadioButtonsExamples = listOf(
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt
new file mode 100644
index 0000000..22d37a9
--- /dev/null
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/PullToRefreshSamples.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2023 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.material3.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.animation.core.animate
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LinearProgressIndicator
+import androidx.compose.material3.ListItem
+import androidx.compose.material3.Text
+import androidx.compose.material3.pulltorefresh.PullToRefreshContainer
+import androidx.compose.material3.pulltorefresh.PullToRefreshState
+import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Velocity
+import kotlinx.coroutines.delay
+
+@Sampled
+@Composable
+@Preview
+@OptIn(ExperimentalMaterial3Api::class)
+fun PullToRefreshSample() {
+    var itemCount by remember { mutableStateOf(15) }
+    val state = rememberPullToRefreshState()
+    if (state.isRefreshing) {
+        LaunchedEffect(true) {
+            // fetch something
+            delay(1500)
+            itemCount += 5
+            state.endRefresh()
+        }
+    }
+    Box(Modifier.nestedScroll(state.nestedScrollConnection)) {
+        LazyColumn(Modifier.fillMaxSize()) {
+            if (!state.isRefreshing) {
+                items(itemCount) {
+                    ListItem({ Text(text = "Item ${itemCount - it}") })
+                }
+            }
+        }
+        PullToRefreshContainer(
+            modifier = Modifier.align(Alignment.TopCenter),
+            state = state,
+        )
+    }
+}
+
+@Sampled
+@Composable
+@Preview
+@OptIn(ExperimentalMaterial3Api::class)
+fun PullToRefreshLinearProgressIndicatorSample() {
+    var itemCount by remember { mutableStateOf(15) }
+    val state = rememberPullToRefreshState()
+    if (state.isRefreshing) {
+        LaunchedEffect(true) {
+            // fetch something
+            delay(1500)
+            itemCount += 5
+            state.endRefresh()
+        }
+    }
+    Box(Modifier.nestedScroll(state.nestedScrollConnection)) {
+        LazyColumn(Modifier.fillMaxSize()) {
+            if (!state.isRefreshing) {
+                items(itemCount) {
+                    ListItem({ Text(text = "Item ${itemCount - it}") })
+                }
+            }
+        }
+        if (state.isRefreshing) {
+            LinearProgressIndicator()
+        } else {
+            LinearProgressIndicator(progress = { state.progress })
+        }
+    }
+}
+
+@Sampled
+@Composable
+@Preview
+@OptIn(ExperimentalMaterial3Api::class)
+fun PullToRefreshSampleCustomState() {
+    var itemCount by remember { mutableStateOf(15) }
+    val state = object : PullToRefreshState {
+        override val positionalThreshold: Float = 100f
+        override val progress get() = verticalOffset / positionalThreshold
+        override var verticalOffset: Float by mutableFloatStateOf(0f)
+        override var isRefreshing: Boolean by mutableStateOf(false)
+        override fun startRefresh() {
+            TODO("Not yet implemented")
+        }
+
+        override fun endRefresh() {
+            TODO("Not yet implemented")
+        }
+
+        // Provide logic for the PullRefreshContainer to consume scrolls within a nested scroll
+        override var nestedScrollConnection: NestedScrollConnection =
+            object : NestedScrollConnection {
+                // Pre and post scroll provide the drag logic for PullRefreshContainer.
+                override fun onPreScroll(
+                    available: Offset,
+                    source: NestedScrollSource,
+                ): Offset = when {
+                    source == NestedScrollSource.Drag && available.y < 0 -> {
+                        // Swiping up
+                        val y = if (isRefreshing) 0f else {
+                            val newOffset = (verticalOffset + available.y).coerceAtLeast(0f)
+                            val dragConsumed = newOffset - verticalOffset
+                            verticalOffset = newOffset
+                            dragConsumed
+                        }
+                        Offset(0f, y)
+                    }
+                    else -> Offset.Zero
+                }
+
+                override fun onPostScroll(
+                    consumed: Offset,
+                    available: Offset,
+                    source: NestedScrollSource
+                ): Offset = when {
+                    source == NestedScrollSource.Drag && available.y > 0 -> {
+                        // Swiping Down
+                        val y = if (isRefreshing) 0f else {
+                            val newOffset = (verticalOffset + available.y).coerceAtLeast(0f)
+                            val dragConsumed = newOffset - verticalOffset
+                            verticalOffset = newOffset
+                            dragConsumed
+                        }
+                        Offset(0f, y)
+                    }
+                    else -> Offset.Zero
+                }
+
+                // Pre-Fling is called when the user releases a drag. This is where you can provide
+                // refresh logic, and verify exceeding positional threshold.
+                override suspend fun onPreFling(available: Velocity): Velocity {
+                    if (isRefreshing) return Velocity.Zero
+                    if (verticalOffset > positionalThreshold) {
+                        isRefreshing = true
+                        itemCount += 5
+                        isRefreshing = false
+                    }
+                    animate(verticalOffset, 0f) { value, _ ->
+                        verticalOffset = value
+                    }
+                    val consumed = when {
+                        verticalOffset == 0f -> 0f
+                        available.y < 0f -> 0f
+                        else -> available.y
+                    }
+                    return Velocity(0f, consumed)
+                }
+            }
+    }
+
+    Box(Modifier.nestedScroll(state.nestedScrollConnection)) {
+        LazyColumn(Modifier.fillMaxSize()) {
+            if (!state.isRefreshing) {
+                items(itemCount) {
+                    ListItem({ Text(text = "Item ${itemCount - it}") })
+                }
+            }
+        }
+        PullToRefreshContainer(
+            modifier = Modifier.align(Alignment.TopCenter),
+            state = state,
+        )
+    }
+}
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SegmentedButtonTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SegmentedButtonTest.kt
index d141417..92f8b4f 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SegmentedButtonTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SegmentedButtonTest.kt
@@ -243,4 +243,22 @@
         assertThat((border.brush as SolidColor).value).isEqualTo(specColor)
         assertThat(border.width).isEqualTo(OutlinedSegmentedButtonTokens.OutlineWidth)
     }
+
+    @Test
+    fun segmentedButtonBorderColor_customColors_resolvesCorrectly() {
+        lateinit var colors: SegmentedButtonColors
+        rule.setMaterialContent(lightColorScheme()) {
+            colors = SegmentedButtonDefaults.colors(
+                activeBorderColor = Color.Magenta,
+                inactiveBorderColor = Color.Cyan,
+                disabledActiveBorderColor = Color.Yellow,
+                disabledInactiveBorderColor = Color.Green,
+            )
+        }
+
+        assertThat(colors.borderColor(active = true, enabled = true)).isEqualTo(Color.Magenta)
+        assertThat(colors.borderColor(active = false, enabled = true)).isEqualTo(Color.Cyan)
+        assertThat(colors.borderColor(active = true, enabled = false)).isEqualTo(Color.Yellow)
+        assertThat(colors.borderColor(active = false, enabled = false)).isEqualTo(Color.Green)
+    }
 }
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pullrefresh/PullRefreshIndicatorScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshIndicatorScreenshotTest.kt
similarity index 73%
rename from compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pullrefresh/PullRefreshIndicatorScreenshotTest.kt
rename to compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshIndicatorScreenshotTest.kt
index 7cefabb..474e79b 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pullrefresh/PullRefreshIndicatorScreenshotTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshIndicatorScreenshotTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.pullrefresh
+package androidx.compose.material3.pulltorefresh
 
 import android.os.Build
 import androidx.compose.foundation.layout.Box
@@ -29,12 +29,12 @@
 import androidx.compose.testutils.assertAgainstGolden
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.unit.Dp
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.screenshot.AndroidXScreenshotTestRule
@@ -63,14 +63,24 @@
         rule.setMaterialContent(scheme.colorScheme) {
             Box(wrap.testTag(testTag)) {
                 val density = LocalDensity.current
-                PullRefreshContainer(
-                    state = object : PullRefreshState {
-                        override val positionalThreshold: Dp
+                PullToRefreshContainer(
+                    state = object : PullToRefreshState {
+                        override val positionalThreshold: Float
                             get() = TODO("Not yet implemented")
                         override val progress = 0.0f
                         override val verticalOffset =
                             with(density) { CircularIndicatorDiameter.toPx() }
-                        override val refreshing = true
+                        override var nestedScrollConnection: NestedScrollConnection
+                            get() = TODO("Not yet implemented")
+                            set(_) {}
+                        override val isRefreshing = true
+                        override fun startRefresh() {
+                            TODO("Not yet implemented")
+                        }
+
+                        override fun endRefresh() {
+                            TODO("Not yet implemented")
+                        }
                     },
                 )
             }
@@ -84,14 +94,24 @@
         rule.setMaterialContent(scheme.colorScheme) {
             Box(wrap.testTag(testTag)) {
                 val density = LocalDensity.current
-                PullRefreshContainer(
-                    state = object : PullRefreshState {
-                        override val positionalThreshold: Dp
+                PullToRefreshContainer(
+                    state = object : PullToRefreshState {
+                        override val positionalThreshold: Float
                             get() = TODO("Not yet implemented")
                         override val progress = 1f
                         override val verticalOffset =
                             with(density) { CircularIndicatorDiameter.toPx() }
-                        override val refreshing = false
+                        override var nestedScrollConnection: NestedScrollConnection
+                            get() = TODO("Not yet implemented")
+                            set(_) {}
+                        override val isRefreshing = false
+                        override fun startRefresh() {
+                            TODO("Not yet implemented")
+                        }
+
+                        override fun endRefresh() {
+                            TODO("Not yet implemented")
+                        }
                     },
                 )
             }
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pullrefresh/PullRefreshIndicatorTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshIndicatorTest.kt
similarity index 67%
rename from compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pullrefresh/PullRefreshIndicatorTest.kt
rename to compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshIndicatorTest.kt
index da13b59..4481eec 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pullrefresh/PullRefreshIndicatorTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshIndicatorTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.pullrefresh
+package androidx.compose.material3.pulltorefresh
 
 import androidx.compose.foundation.gestures.awaitEachGesture
 import androidx.compose.foundation.gestures.awaitFirstDown
@@ -27,6 +27,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.pointer.PointerInputChange
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.layout.onSizeChanged
@@ -38,7 +39,6 @@
 import androidx.compose.ui.test.onChild
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.performClick
-import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -51,7 +51,7 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 @OptIn(ExperimentalMaterial3Api::class)
-class PullRefreshIndicatorTest {
+class PullToRefreshIndicatorTest {
 
     @get:Rule
     val rule = createComposeRule()
@@ -61,13 +61,23 @@
         rule.setContent {
             val density = LocalDensity.current
             Box(Modifier.fillMaxSize()) {
-                PullRefreshContainer(
-                    state = object : PullRefreshState {
-                        override val positionalThreshold: Dp
+                PullToRefreshContainer(
+                    state = object : PullToRefreshState {
+                        override val positionalThreshold: Float
                             get() = TODO("Not yet implemented")
                         override val progress = 0.5f
                         override val verticalOffset = with(density) { 50.dp.toPx() }
-                        override val refreshing = true
+                        override var nestedScrollConnection: NestedScrollConnection
+                            get() = TODO("Not yet implemented")
+                            set(_) {}
+                        override val isRefreshing = true
+                        override fun startRefresh() {
+                            TODO("Not yet implemented")
+                        }
+
+                        override fun endRefresh() {
+                            TODO("Not yet implemented")
+                        }
                     },
                     modifier = Modifier.testTag(INDICATOR_TAG)
                 )
@@ -81,13 +91,23 @@
         rule.setContent {
             val density = LocalDensity.current
             Box(Modifier.fillMaxSize()) {
-                PullRefreshContainer(
-                    state = object : PullRefreshState {
-                        override val positionalThreshold: Dp
+                PullToRefreshContainer(
+                    state = object : PullToRefreshState {
+                        override val positionalThreshold: Float
                             get() = TODO("Not yet implemented")
                         override val progress = 0.5f
                         override val verticalOffset = with(density) { 50.dp.toPx() }
-                        override val refreshing = false
+                        override var nestedScrollConnection: NestedScrollConnection
+                            get() = TODO("Not yet implemented")
+                            set(_) {}
+                        override val isRefreshing = false
+                        override fun startRefresh() {
+                            TODO("Not yet implemented")
+                        }
+
+                        override fun endRefresh() {
+                            TODO("Not yet implemented")
+                        }
                     },
                     modifier = Modifier.testTag(INDICATOR_TAG)
                 )
@@ -102,14 +122,24 @@
         rule.setContent {
             val density = LocalDensity.current
             Box(Modifier.fillMaxSize()) {
-                PullRefreshContainer(
-                    state = object : PullRefreshState {
-                        override val positionalThreshold: Dp
+                PullToRefreshContainer(
+                    state = object : PullToRefreshState {
+                        override val positionalThreshold: Float
                             get() = TODO("Not yet implemented")
                         override val progress = 0.5f
                         override val verticalOffset =
                             with(density) { verticalOffsetDp.value.toPx() }
-                        override val refreshing = false
+                        override var nestedScrollConnection: NestedScrollConnection
+                            get() = TODO("Not yet implemented")
+                            set(_) {}
+                        override val isRefreshing = false
+                        override fun startRefresh() {
+                            TODO("Not yet implemented")
+                        }
+
+                        override fun endRefresh() {
+                            TODO("Not yet implemented")
+                        }
                     },
                     modifier = Modifier.heightIn(min = 30.dp).testTag(INDICATOR_TAG)
                 )
@@ -143,13 +173,23 @@
                         downEvent = awaitFirstDown()
                     }
                 })
-                PullRefreshContainer(
-                    state = object : PullRefreshState {
-                        override val positionalThreshold: Dp
+                PullToRefreshContainer(
+                    state = object : PullToRefreshState {
+                        override val positionalThreshold: Float
                             get() = TODO("Not yet implemented")
                         override val progress = 0f
                         override val verticalOffset = verticalOffset
-                        override val refreshing = false
+                        override var nestedScrollConnection: NestedScrollConnection
+                            get() = TODO("Not yet implemented")
+                            set(_) {}
+                        override val isRefreshing = false
+                        override fun startRefresh() {
+                            TODO("Not yet implemented")
+                        }
+
+                        override fun endRefresh() {
+                            TODO("Not yet implemented")
+                        }
                     },
                     modifier = Modifier.onSizeChanged {
                         // The indicator starts as offset by its negative height in the y direction,
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshStateImplTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshStateImplTest.kt
new file mode 100644
index 0000000..1233c28
--- /dev/null
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/pulltorefresh/PullToRefreshStateImplTest.kt
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2023 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.material3.pulltorefresh
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Text
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.junit4.StateRestorationTester
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeDown
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterial3Api::class)
+class PullToRefreshStateImplTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun refreshTrigger_onlyAfterThreshold() {
+        var refreshCount = 0
+        var touchSlop = 0f
+        val positionalThreshold = 400f
+        lateinit var state: PullToRefreshState
+
+        rule.setContent {
+            touchSlop = LocalViewConfiguration.current.touchSlop
+            state = remember {
+                PullToRefreshStateImpl(
+                    initialRefreshing = false,
+                    positionalThreshold = positionalThreshold,
+                    enabled = { true },
+                )
+            }
+            if (state.isRefreshing) {
+                LaunchedEffect(true) {
+                    refreshCount++
+                    state.endRefresh()
+                }
+            }
+            Box(
+                Modifier
+                    .nestedScroll(state.nestedScrollConnection)
+                    .testTag(PullRefreshTag)) {
+                LazyColumn {
+                    items(100) {
+                        Text("item $it")
+                    }
+                }
+            }
+        }
+        // Account for DragModifier - pull down twice the threshold value.
+
+        // Less than threshold
+        pullRefreshNode.performTouchInput {
+            swipeDown(endY = 2 * positionalThreshold + touchSlop - 1f)
+        }
+
+        rule.waitForIdle()
+
+        // Equal to threshold
+        pullRefreshNode.performTouchInput {
+            swipeDown(endY = 2 * positionalThreshold + touchSlop)
+        }
+
+        rule.runOnIdle {
+            assertThat(refreshCount).isEqualTo(0)
+            // Since onRefresh was not called, we should reset the position back to 0
+            assertThat(state.progress).isEqualTo(0f)
+            assertThat(state.verticalOffset).isEqualTo(0f)
+        }
+
+        pullRefreshNode.performTouchInput {
+            swipeDown(endY = 2 * positionalThreshold + touchSlop + 1f)
+        }
+        rule.runOnIdle { assertThat(refreshCount).isEqualTo(1) }
+    }
+
+    @Test
+    fun progressAndVerticalOffset_scaleCorrectly_untilThreshold() {
+        lateinit var state: PullToRefreshStateImpl
+        var refreshCount = 0
+        val positionalThreshold = 400f
+
+        rule.setContent {
+            state = remember {
+                PullToRefreshStateImpl(
+                    initialRefreshing = false,
+                    positionalThreshold = positionalThreshold,
+                    enabled = { true },
+                )
+            }
+            if (state.isRefreshing) {
+                LaunchedEffect(true) {
+                    refreshCount++
+                    state.endRefresh()
+                }
+            }
+            Box(
+                Modifier
+                    .nestedScroll(state.nestedScrollConnection)
+                    .testTag(PullRefreshTag)) {
+                LazyColumn {
+                    items(100) {
+                        Text("item $it")
+                    }
+                }
+            }
+        }
+
+        state.distancePulled = positionalThreshold
+        rule.runOnIdle {
+            // Expected values given drag modifier of 0.5f
+            assertThat(state.progress).isEqualTo(0.5f)
+            assertThat(state.calculateVerticalOffset()).isEqualTo(200f)
+            assertThat(refreshCount).isEqualTo(0)
+        }
+    }
+
+    @Test
+    fun progressAndPosition_scaleCorrectly_beyondThreshold() {
+        lateinit var state: PullToRefreshStateImpl
+        lateinit var scope: CoroutineScope
+        var refreshCount = 0
+        val positionalThreshold = 400f
+
+        rule.setContent {
+            state = remember {
+                PullToRefreshStateImpl(
+                    initialRefreshing = false,
+                    positionalThreshold = positionalThreshold,
+                    enabled = { true },
+                )
+            }
+            scope = rememberCoroutineScope()
+            if (state.isRefreshing) {
+                LaunchedEffect(true) {
+                    refreshCount++
+                    state.endRefresh()
+                }
+            }
+            Box(
+                Modifier
+                    .nestedScroll(state.nestedScrollConnection)
+                    .testTag(PullRefreshTag)) {
+                LazyColumn {
+                    items(100) {
+                        Text("item $it")
+                    }
+                }
+            }
+        }
+
+        state.distancePulled = 2 * positionalThreshold
+        rule.runOnIdle {
+            assertThat(state.progress).isEqualTo(1f)
+            // Account for PullMultiplier.
+            assertThat(state.calculateVerticalOffset()).isEqualTo(positionalThreshold)
+            assertThat(refreshCount).isEqualTo(0)
+        }
+
+        state.distancePulled += positionalThreshold
+
+        rule.runOnIdle {
+            assertThat(state.progress).isEqualTo(1.5f)
+            assertThat(refreshCount).isEqualTo(0)
+        }
+
+        scope.launch { state.onRelease(0f) }
+        rule.runOnIdle {
+            assertThat(state.progress).isEqualTo(0f)
+            assertThat(refreshCount).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun positionIsCapped() {
+        lateinit var state: PullToRefreshStateImpl
+        var refreshCount = 0
+        val positionalThreshold = 400f
+
+        rule.setContent {
+            state = remember {
+                PullToRefreshStateImpl(
+                    initialRefreshing = false,
+                    positionalThreshold = positionalThreshold,
+                    enabled = { true },
+                )
+            }
+            if (state.isRefreshing) {
+                LaunchedEffect(true) {
+                    refreshCount++
+                    state.endRefresh()
+                }
+            }
+            Box(
+                Modifier
+                    .nestedScroll(state.nestedScrollConnection)
+                    .testTag(PullRefreshTag)) {
+                LazyColumn {
+                    items(100) {
+                        Text("item $it")
+                    }
+                }
+            }
+        }
+        state.distancePulled = 10 * positionalThreshold
+
+        rule.runOnIdle {
+            assertThat(state.progress).isEqualTo(5f) // Account for PullMultiplier.
+            // Indicator position is capped to 2 times the refresh threshold.
+            assertThat(state.calculateVerticalOffset()).isEqualTo(2 * positionalThreshold)
+            assertThat(refreshCount).isEqualTo(0)
+        }
+    }
+
+    @Test
+    fun nestedPreScroll_negativeDelta_notRefreshing() {
+        var refreshCount = 0
+        val positionalThreshold = 200f
+        lateinit var state: PullToRefreshStateImpl
+        val dispatcher = NestedScrollDispatcher()
+        val connection = object : NestedScrollConnection {}
+
+        rule.setContent {
+            state = remember {
+                PullToRefreshStateImpl(
+                    initialRefreshing = false,
+                    positionalThreshold = positionalThreshold,
+                    enabled = { true },
+                )
+            }
+            if (state.isRefreshing) {
+                LaunchedEffect(true) {
+                    refreshCount++
+                    state.endRefresh()
+                }
+            }
+            Box(
+                Modifier
+                    .nestedScroll(state.nestedScrollConnection)
+                    .testTag(PullRefreshTag)) {
+                Box(
+                    Modifier
+                        .size(100.dp)
+                        .nestedScroll(connection, dispatcher))
+            }
+        }
+        // 100 pixels up
+        val dragUpOffset = Offset(0f, -100f)
+
+        rule.runOnIdle {
+            val preConsumed = dispatcher.dispatchPreScroll(dragUpOffset, NestedScrollSource.Drag)
+            // Pull refresh is not showing, so we should consume nothing
+            assertThat(preConsumed).isEqualTo(Offset.Zero)
+            assertThat(state.verticalOffset).isEqualTo(0f)
+        }
+
+        // Pull the state by a bit
+        state.distancePulled = 200f
+
+        rule.runOnIdle {
+            assertThat(state.calculateVerticalOffset())
+                .isEqualTo(100f /* 200 / 2 for drag multiplier */)
+            val preConsumed = dispatcher.dispatchPreScroll(dragUpOffset, NestedScrollSource.Drag)
+            // Pull refresh is currently showing, so we should consume all the delta
+            assertThat(preConsumed).isEqualTo(dragUpOffset)
+            assertThat(state.calculateVerticalOffset())
+                .isEqualTo(50f /* (200 - 100) / 2 for drag multiplier */)
+        }
+    }
+
+    @Test
+    fun state_restoresPullRefreshState() {
+        val restorationTester = StateRestorationTester(rule)
+        var pullToRefreshState: PullToRefreshState? = null
+        lateinit var scope: CoroutineScope
+        restorationTester.setContent {
+            pullToRefreshState = rememberPullToRefreshState()
+            scope = rememberCoroutineScope()
+        }
+
+        with(pullToRefreshState!!) {
+            rule.runOnIdle { scope.launch { startRefresh() } }
+            pullToRefreshState = null
+            restorationTester.emulateSavedInstanceStateRestore()
+            assertThat(isRefreshing).isTrue()
+        }
+    }
+
+    private val PullRefreshTag = "PullRefresh"
+    private val pullRefreshNode = rule.onNodeWithTag(PullRefreshTag)
+}
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/ExposedDropdownMenuPopup.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/ExposedDropdownMenuPopup.android.kt
index 67a996d..9089e62 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/ExposedDropdownMenuPopup.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/internal/ExposedDropdownMenuPopup.android.kt
@@ -28,6 +28,7 @@
 import android.view.ViewOutlineProvider
 import android.view.ViewTreeObserver
 import android.view.WindowManager
+import android.view.accessibility.AccessibilityManager
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionContext
 import androidx.compose.runtime.DisposableEffect
@@ -43,12 +44,13 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.R
 import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.toComposeIntRect
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.layout.positionInWindow
 import androidx.compose.ui.platform.AbstractComposeView
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.LocalView
@@ -85,16 +87,21 @@
     val view = LocalView.current
     val density = LocalDensity.current
     val layoutDirection = LocalLayoutDirection.current
+    val context = LocalContext.current
+    val a11yManager =
+        context.getSystemService(Context.ACCESSIBILITY_SERVICE) as? AccessibilityManager
+
     val parentComposition = rememberCompositionContext()
     val currentContent by rememberUpdatedState(content)
     val popupId = rememberSaveable { UUID.randomUUID() }
-    val popupLayout = remember {
+    val popupLayout = remember(a11yManager) {
         PopupLayout(
             >
             composeView = view,
             positionProvider = popupPositionProvider,
+            focusable = a11yManager?.isTouchExplorationEnabled == true,
             density = density,
-            popupId = popupId
+            popupId = popupId,
         ).apply {
             setContent(parentComposition) {
                 SimpleStack(
@@ -200,6 +207,7 @@
     private var onDismissRequest: (() -> Unit)?,
     private val composeView: View,
     private val positionProvider: PopupPositionProvider,
+    private val focusable: Boolean,
     density: Density,
     popupId: UUID
 ) : AbstractComposeView(composeView.context),
@@ -312,10 +320,9 @@
         val parentBounds = parentBounds ?: return
         val popupContentSize = popupContentSize ?: return
 
-        val windowSize = previousWindowVisibleFrame.let {
-            composeView.getWindowVisibleDisplayFrame(it)
-            val bounds = it.toIntBounds()
-            IntSize(width = bounds.width, height = bounds.height)
+        val windowSize = previousWindowVisibleFrame.let { rect ->
+            composeView.getWindowVisibleDisplayFrame(rect)
+            rect.toComposeIntRect().size
         }
 
         val popupPosition = positionProvider.calculatePosition(
@@ -355,14 +362,11 @@
             (event.action == MotionEvent.ACTION_DOWN &&
                 (event.x < 0 || event.x >= width || event.y < 0 || event.y >= height))
         ) {
-            val parentBounds = parentBounds
-            val shouldDismiss = parentBounds == null || dismissOnOutsideClick(
-                // Keep menu open if ACTION_OUTSIDE event is reported as raw coordinates of (0, 0).
-                // This means it belongs to another owner, e.g., the soft keyboard or other window.
-                if (event.rawX != 0f && event.rawY != 0f) Offset(event.rawX, event.rawY) else null,
-                parentBounds
-            )
+            // If an event has raw coordinates of (0, 0), it means it belongs to another owner,
+            // e.g., the soft keyboard or other window, so we want to keep the menu open.
+            val isOutsideClickOnKeyboard = event.rawX == 0f && event.rawY == 0f
 
+            val shouldDismiss = parentBounds == null || !isOutsideClickOnKeyboard
             if (shouldDismiss) {
                 onDismissRequest?.invoke()
                 return true
@@ -385,15 +389,6 @@
         super.setLayoutDirection(direction)
     }
 
-    // Specific to exposed dropdown menus.
-    private fun dismissOnOutsideClick(offset: Offset?, bounds: IntRect): Boolean =
-        if (offset == null) {
-            false
-        } else {
-            offset.x < bounds.left || offset.x > bounds.right ||
-                offset.y < bounds.top || offset.y > bounds.bottom
-        }
-
     /**
      * Initialize the LayoutParams specific to [android.widget.PopupWindow].
      */
@@ -403,9 +398,15 @@
             gravity = Gravity.START or Gravity.TOP
 
             // Flags specific to exposed dropdown menu.
-            flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
-                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
+            flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH and
+                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL.inv() or
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+            flags = if (focusable) {
+                flags and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv()
+            } else {
+                flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+            }
+
             softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
 
             type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
@@ -425,13 +426,6 @@
         }
     }
 
-    private fun Rect.toIntBounds() = IntRect(
-        left = left,
-        top = top,
-        right = right,
-        bottom = bottom
-    )
-
     override fun onGlobalLayout() {
         // Update the position of the popup, in case getWindowVisibleDisplayFrame has changed.
         composeView.getWindowVisibleDisplayFrame(tmpWindowVisibleFrame)
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt
index 6cea7dd..643d21e 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt
@@ -625,8 +625,8 @@
         return when {
             enabled && active -> activeBorderColor
             enabled && !active -> inactiveBorderColor
-            !enabled && active -> disabledActiveContentColor
-            else -> disabledInactiveContentColor
+            !enabled && active -> disabledActiveBorderColor
+            else -> disabledInactiveBorderColor
         }
     }
 
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pullrefresh/PullRefresh.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pullrefresh/PullRefresh.kt
deleted file mode 100644
index 9cafffb..0000000
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pullrefresh/PullRefresh.kt
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright 2023 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.material3.pullrefresh
-
-import androidx.annotation.FloatRange
-import androidx.compose.animation.Crossfade
-import androidx.compose.animation.core.LinearEasing
-import androidx.compose.animation.core.animateFloatAsState
-import androidx.compose.animation.core.tween
-import androidx.compose.foundation.Canvas
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material3.CircularIndicatorDiameter
-import androidx.compose.material3.CircularProgressIndicator
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.LocalContentColor
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.contentColorFor
-import androidx.compose.material3.pullrefresh.PullRefreshDefaults.Indicator
-import androidx.compose.material3.tokens.MotionTokens
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.shadow
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.geometry.center
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Path
-import androidx.compose.ui.graphics.PathFillType
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.StrokeCap
-import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.drawscope.Stroke
-import androidx.compose.ui.graphics.drawscope.rotate
-import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.semantics.ProgressBarRangeInfo
-import androidx.compose.ui.semantics.progressBarRangeInfo
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import kotlin.math.abs
-import kotlin.math.max
-import kotlin.math.min
-import kotlin.math.pow
-
-// TODO: Provide samples once PullRefreshState implementation lands
-/**
- * Material Design pull refresh indicator
- *
- * @param state the state of this [PullRefreshContainer]
- * @param modifier the [Modifier] to be applied to this container
- * @param indicator The indicator placed inside of the [PullRefreshContainer]. Has access to [state]
- * @param shape the [Shape] of this container
- * @param containerColor the color of this container
- * @param contentColor the color of the progress indicator
- */
-@Composable
-@ExperimentalMaterial3Api
-@Suppress("ComposableLambdaParameterPosition")
-internal fun PullRefreshContainer(
-    state: PullRefreshState,
-    modifier: Modifier = Modifier,
-    indicator: @Composable (PullRefreshState) -> Unit = { pullRefreshState ->
-        Indicator(state = pullRefreshState)
-    },
-    shape: Shape = PullRefreshDefaults.shape,
-    containerColor: Color = PullRefreshDefaults.containerColor,
-    contentColor: Color = contentColorFor(backgroundColor = containerColor),
-) {
-    // Surface is not used here, as we do not want its input-blocking behaviour, since the indicator
-    // is typically displayed above other (possibly) interactive indicator.
-    val showElevation = remember {
-        derivedStateOf { state.refreshing || state.verticalOffset > 0.5f }
-    }
-    CompositionLocalProvider(LocalContentColor provides contentColor) {
-        Box(
-            modifier = modifier
-                .size(CircularIndicatorDiameter)
-                .graphicsLayer {
-                    translationY = state.verticalOffset - size.height
-                }
-                .shadow(
-                    // Avoid shadow when indicator is hidden
-                    elevation = if (showElevation.value) Elevation else 0.dp,
-                    shape = shape,
-                    clip = true
-                )
-                .background(color = containerColor, shape = shape)
-        ) {
-            indicator(state)
-        }
-    }
-}
-
-/**
- * Contains the default values for [PullRefreshContainer]
- */
-@ExperimentalMaterial3Api
-internal object PullRefreshDefaults {
-
-    /** The default shape for [PullRefreshContainer] */
-    val shape: Shape = CircleShape
-
-    /** The default container color for [PullRefreshContainer] */
-    val containerColor: Color @Composable get() = MaterialTheme.colorScheme.surfaceContainerHigh
-
-    /**
-     * The default indicator for [PullRefreshContainer].
-     */
-    @Composable
-    fun Indicator(
-        state: PullRefreshState,
-        modifier: Modifier = Modifier,
-        color: Color = LocalContentColor.current,
-    ) {
-        Crossfade(
-            targetState = state.refreshing,
-            animationSpec = tween(durationMillis = CrossfadeDurationMs)
-        ) { refreshing ->
-            Box(
-                modifier = modifier.fillMaxSize(),
-                contentAlignment = Alignment.Center
-            ) {
-                if (refreshing) {
-                    CircularProgressIndicator(
-                        strokeWidth = StrokeWidth,
-                        color = color,
-                        modifier = Modifier.size(SpinnerSize),
-                    )
-                } else {
-                    CircularArrowProgressIndicator(
-                        progress = { state.progress },
-                        color = color,
-                        strokeWidth = StrokeWidth,
-                    )
-                }
-            }
-        }
-    }
-}
-
-/**
- * The state that is associated with a [PullRefreshContainer].
- * Each instance of [PullRefreshContainer] should have its own [PullRefreshState].
- */
-@Stable
-@ExperimentalMaterial3Api
-internal interface PullRefreshState {
-    /** The threshold above which, if a release occurs, a refresh will be called */
-    val positionalThreshold: Dp
-
-    /**
-     * PullRefresh progress towards [positionalThreshold]. 0.0 indicates no progress, 1.0 indicates
-     * complete progress, > 1.0 indicates overshoot beyond the provided threshold
-     */
-    @get:FloatRange(from = 0.0)
-    val progress: Float
-
-    /**
-     * Indicates whether a refresh is occurring
-     */
-    val refreshing: Boolean
-
-    /**
-     * The vertical offset (in pixels) for the [PullRefreshContainer] to consume
-     */
-    @get:FloatRange(from = 0.0)
-    val verticalOffset: Float
-}
-
-/** The default pull indicator for [PullRefreshContainer] */
-@Composable
-private fun CircularArrowProgressIndicator(
-    progress: () -> Float,
-    color: Color,
-    strokeWidth: Dp,
-    modifier: Modifier = Modifier,
-) {
-    val path = remember { Path().apply { fillType = PathFillType.EvenOdd } }
-    // TODO: Consider refactoring this sub-component utilizing Modifier.Node
-    val targetAlpha by remember {
-        derivedStateOf { if (progress() >= 1f) MaxAlpha else MinAlpha }
-    }
-    val alphaState = animateFloatAsState(targetValue = targetAlpha, animationSpec = AlphaTween)
-    Canvas(
-        modifier
-            .semantics(mergeDescendants = true) {
-                progressBarRangeInfo =
-                    ProgressBarRangeInfo(progress(), 0f..1f, 0)
-            }
-            .size(SpinnerSize)
-    ) {
-        val values = ArrowValues(progress())
-        val alpha = alphaState.value
-        rotate(degrees = values.rotation) {
-            val arcRadius = ArcRadius.toPx() + strokeWidth.toPx() / 2f
-            val arcBounds = Rect(center = size.center, radius = arcRadius)
-            drawCircularIndicator(color, alpha, values, arcBounds, strokeWidth)
-            drawArrow(path, arcBounds, color, alpha, values, strokeWidth)
-        }
-    }
-}
-
-private fun DrawScope.drawCircularIndicator(
-    color: Color,
-    alpha: Float,
-    values: ArrowValues,
-    arcBounds: Rect,
-    strokeWidth: Dp
-) {
-    drawArc(
-        color = color,
-        alpha = alpha,
-        startAngle = values.startAngle,
-        sweepAngle = values.endAngle - values.startAngle,
-        useCenter = false,
-        topLeft = arcBounds.topLeft,
-        size = arcBounds.size,
-        style = Stroke(
-            width = strokeWidth.toPx(),
-            cap = StrokeCap.Square
-        )
-    )
-}
-
-@Immutable
-private class ArrowValues(
-    val rotation: Float,
-    val startAngle: Float,
-    val endAngle: Float,
-    val scale: Float
-)
-
-private fun ArrowValues(progress: Float): ArrowValues {
-    // Discard first 40% of progress. Scale remaining progress to full range between 0 and 100%.
-    val adjustedPercent = max(min(1f, progress) - 0.4f, 0f) * 5 / 3
-    // How far beyond the threshold pull has gone, as a percentage of the threshold.
-    val overshootPercent = abs(progress) - 1.0f
-    // Limit the overshoot to 200%. Linear between 0 and 200.
-    val linearTension = overshootPercent.coerceIn(0f, 2f)
-    // Non-linear tension. Increases with linearTension, but at a decreasing rate.
-    val tensionPercent = linearTension - linearTension.pow(2) / 4
-
-    // Calculations based on SwipeRefreshLayout specification.
-    val endTrim = adjustedPercent * MaxProgressArc
-    val rotation = (-0.25f + 0.4f * adjustedPercent + tensionPercent) * 0.5f
-    val startAngle = rotation * 360
-    val endAngle = (rotation + endTrim) * 360
-    val scale = min(1f, adjustedPercent)
-
-    return ArrowValues(rotation, startAngle, endAngle, scale)
-}
-
-private fun DrawScope.drawArrow(
-    arrow: Path,
-    bounds: Rect,
-    color: Color,
-    alpha: Float,
-    values: ArrowValues,
-    strokeWidth: Dp,
-) {
-    arrow.reset()
-    arrow.moveTo(0f, 0f) // Move to left corner
-    arrow.lineTo(x = ArrowWidth.toPx() * values.scale, y = 0f) // Line to right corner
-
-    // Line to tip of arrow
-    arrow.lineTo(
-        x = ArrowWidth.toPx() * values.scale / 2,
-        y = ArrowHeight.toPx() * values.scale
-    )
-
-    val radius = min(bounds.width, bounds.height) / 2f
-    val inset = ArrowWidth.toPx() * values.scale / 2f
-    arrow.translate(
-        Offset(
-            x = radius + bounds.center.x - inset,
-            y = bounds.center.y + strokeWidth.toPx() / 2f
-        )
-    )
-    arrow.close()
-    rotate(degrees = values.endAngle) {
-        drawPath(path = arrow, color = color, alpha = alpha)
-    }
-}
-
-private const val MaxProgressArc = 0.8f
-private const val CrossfadeDurationMs = MotionTokens.DurationShort2.toInt()
-
-/** The default stroke width for [Indicator] */
-private val StrokeWidth = 2.5.dp
-
-private val ArcRadius = 7.5.dp
-private val SpinnerSize = 20.dp // (ArcRadius + PullRefreshIndicatorDefaults.StrokeWidth).times(2)
-private val Elevation = 6.dp
-private val ArrowWidth = 10.dp
-private val ArrowHeight = 5.dp
-
-// Values taken from SwipeRefreshLayout
-private const val MinAlpha = 0.3f
-private const val MaxAlpha = 1f
-private val AlphaTween = tween<Float>(MotionTokens.DurationMedium2.toInt(), easing = LinearEasing)
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt
new file mode 100644
index 0000000..c6b2782
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/pulltorefresh/PullToRefresh.kt
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2023 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.material3.pulltorefresh
+
+import androidx.annotation.FloatRange
+import androidx.compose.animation.Crossfade
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.animate
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.CircularIndicatorDiameter
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator
+import androidx.compose.material3.tokens.ElevationTokens
+import androidx.compose.material3.tokens.MotionTokens
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.center
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.PathFillType
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.graphics.drawscope.rotate
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.ProgressBarRangeInfo
+import androidx.compose.ui.semantics.progressBarRangeInfo
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.unit.dp
+import kotlin.math.abs
+import kotlin.math.max
+import kotlin.math.min
+import kotlin.math.pow
+
+// TODO: Link to Material design specs when available.
+/**
+ * Material Design pull-to-refresh indicator
+ *
+ * A pull-to-refresh container contains a progress indicator to indicate a users drag progress
+ * towards triggering a refresh. On a refresh the progress indicator inside this container is
+ * indeterminate.
+ *
+ * @sample androidx.compose.material3.samples.PullToRefreshSample
+ *
+ * A custom state implementation can be initialized like this
+ * @sample androidx.compose.material3.samples.PullToRefreshSampleCustomState
+ *
+ * @param state the state of this [PullToRefreshContainer]
+ * @param modifier the [Modifier] to be applied to this container
+ * @param indicator The indicator placed inside of the [PullToRefreshContainer]. Has access to
+ * [state]
+ * @param shape the [Shape] of this container
+ * @param containerColor the color of this container
+ * @param contentColor the color of the progress indicator
+ */
+@Composable
+@ExperimentalMaterial3Api
+@Suppress("ComposableLambdaParameterPosition")
+fun PullToRefreshContainer(
+    state: PullToRefreshState,
+    modifier: Modifier = Modifier,
+    indicator: @Composable (PullToRefreshState) -> Unit = { pullRefreshState ->
+        Indicator(state = pullRefreshState)
+    },
+    shape: Shape = PullToRefreshDefaults.shape,
+    containerColor: Color = PullToRefreshDefaults.containerColor,
+    contentColor: Color = PullToRefreshDefaults.contentColor,
+) {
+    // Surface is not used here, as we do not want its input-blocking behaviour, since the indicator
+    // is typically displayed above other (possibly) interactive indicator.
+    val showElevation = remember {
+        derivedStateOf { state.verticalOffset > 1f || state.isRefreshing }
+    }
+    CompositionLocalProvider(LocalContentColor provides contentColor) {
+        Box(
+            modifier = modifier
+                .size(CircularIndicatorDiameter)
+                .graphicsLayer {
+                    translationY = state.verticalOffset - size.height
+                }
+                .shadow(
+                    // Avoid shadow when indicator is hidden
+                    elevation = if (showElevation.value) Elevation else 0.dp,
+                    shape = shape,
+                    clip = true
+                )
+                .background(color = containerColor, shape = shape)
+        ) {
+            indicator(state)
+        }
+    }
+}
+
+/**
+ * Contains the default values for [PullToRefreshContainer]
+ */
+@ExperimentalMaterial3Api
+object PullToRefreshDefaults {
+    /** The default shape for [PullToRefreshContainer] */
+    val shape: Shape = CircleShape
+
+    /** The default container color for [PullToRefreshContainer] */
+    val containerColor: Color @Composable get() = MaterialTheme.colorScheme.surfaceContainerHigh
+
+    /** The default container color for [PullToRefreshContainer] */
+    val contentColor: Color @Composable get() = MaterialTheme.colorScheme.onSurfaceVariant
+
+    /** The default refresh threshold for [rememberPullToRefreshState] */
+    val PositionalThreshold = 80.dp
+
+    /**
+     * The default indicator for [PullToRefreshContainer].
+     */
+    @Composable
+    fun Indicator(
+        state: PullToRefreshState,
+        modifier: Modifier = Modifier,
+        color: Color = LocalContentColor.current,
+    ) {
+        Crossfade(
+            targetState = state.isRefreshing,
+            animationSpec = tween(durationMillis = CrossfadeDurationMs)
+        ) { refreshing ->
+            Box(
+                modifier = modifier.fillMaxSize(),
+                contentAlignment = Alignment.Center
+            ) {
+                if (refreshing) {
+                    CircularProgressIndicator(
+                        strokeWidth = StrokeWidth,
+                        color = color,
+                        modifier = Modifier.size(SpinnerSize),
+                    )
+                } else {
+                    CircularArrowProgressIndicator(
+                        progress = { state.progress },
+                        color = color,
+                    )
+                }
+            }
+        }
+    }
+}
+
+/**
+ * The state that is associated with a [PullToRefreshContainer].
+ * Each instance of [PullToRefreshContainer] should have its own [PullToRefreshState].
+ *
+ * [PullToRefreshState] can be used with other progress indicators like so:
+ * @sample androidx.compose.material3.samples.PullToRefreshLinearProgressIndicatorSample
+ */
+@Stable
+@ExperimentalMaterial3Api
+interface PullToRefreshState {
+    /** The threshold (in pixels), above which if a release occurs, a refresh will be called */
+    val positionalThreshold: Float
+
+    /**
+     * PullRefresh progress towards [positionalThreshold]. 0.0 indicates no progress, 1.0 indicates
+     * complete progress, > 1.0 indicates overshoot beyond the provided threshold
+     */
+    @get:FloatRange(from = 0.0)
+    val progress: Float
+
+    /**
+     * Indicates whether a refresh is occurring.
+     */
+    val isRefreshing: Boolean
+
+    /**
+     * Sets [isRefreshing] to true.
+     */
+    fun startRefresh()
+
+    /**
+     * Sets [isRefreshing] to false.
+     */
+    fun endRefresh()
+
+    /**
+     * The vertical offset (in pixels) for the [PullToRefreshContainer] to consume
+     */
+    @get:FloatRange(from = 0.0)
+    val verticalOffset: Float
+
+    /**
+     * A [NestedScrollConnection] that should be attached to a [Modifier.nestedScroll] in order to
+     * keep track of the scroll events.
+     */
+    var nestedScrollConnection: NestedScrollConnection
+}
+
+/**
+ * Create and remember the default [PullToRefreshState].
+ *
+ * @param positionalThreshold The positional threshold when a refresh would be triggered
+ * @param enabled a callback used to determine whether scroll events are to be handled by this
+ * [PullToRefreshState]
+ */
+@Composable
+@ExperimentalMaterial3Api
+fun rememberPullToRefreshState(
+    positionalThreshold: Dp = PullToRefreshDefaults.PositionalThreshold,
+    enabled: () -> Boolean = { true },
+): PullToRefreshState {
+    val density = LocalDensity.current
+    val positionalThresholdPx = with(density) { positionalThreshold.toPx() }
+    return rememberSaveable(
+        positionalThresholdPx, enabled,
+        saver = PullToRefreshStateImpl.Saver(
+            positionalThreshold = positionalThresholdPx,
+            enabled = enabled,
+        )
+    ) {
+        PullToRefreshStateImpl(
+            initialRefreshing = false,
+            positionalThreshold = positionalThresholdPx,
+            enabled = enabled,
+        )
+    }
+}
+
+/**
+ * Creates a [PullToRefreshState].
+ *
+ * Note that in most cases, you are advised to use [rememberPullToRefreshState] when in composition.
+ *
+ * @param positionalThresholdPx The positional threshold, in pixels, in which a refresh is triggered
+ * @param initialRefreshing The initial refreshing value of [PullToRefreshState]
+ * @param enabled a callback used to determine whether scroll events are to be handled by this
+ * [PullToRefreshState]
+ */
+@ExperimentalMaterial3Api
+fun PullToRefreshState(
+    positionalThresholdPx: Float,
+    initialRefreshing: Boolean = false,
+    enabled: () -> Boolean = { true },
+): PullToRefreshState = PullToRefreshStateImpl(
+    initialRefreshing = initialRefreshing,
+    positionalThreshold = positionalThresholdPx,
+    enabled = enabled,
+)
+
+@ExperimentalMaterial3Api
+internal class PullToRefreshStateImpl(
+    initialRefreshing: Boolean,
+    override val positionalThreshold: Float,
+    enabled: () -> Boolean,
+) : PullToRefreshState {
+
+    override val progress get() = adjustedDistancePulled / positionalThreshold
+    override val verticalOffset get() = _verticalOffset
+
+    override val isRefreshing get() = _refreshing
+
+    override fun startRefresh() {
+        _refreshing = true
+        _verticalOffset = positionalThreshold
+    }
+
+    override fun endRefresh() {
+        _verticalOffset = 0f
+        _refreshing = false
+    }
+
+    override var nestedScrollConnection = object : NestedScrollConnection {
+        override fun onPreScroll(
+            available: Offset,
+            source: NestedScrollSource,
+        ): Offset = when {
+            !enabled() -> Offset.Zero
+            // Swiping up
+            source == NestedScrollSource.Drag && available.y < 0 -> {
+                consumeAvailableOffset(available)
+            }
+            else -> Offset.Zero
+        }
+
+        override fun onPostScroll(
+            consumed: Offset,
+            available: Offset,
+            source: NestedScrollSource
+        ): Offset = when {
+            !enabled() -> Offset.Zero
+            // Swiping down
+            source == NestedScrollSource.Drag && available.y > 0 -> {
+                consumeAvailableOffset(available)
+            }
+            else -> Offset.Zero
+        }
+
+        override suspend fun onPreFling(available: Velocity): Velocity {
+            return Velocity(0f, onRelease(available.y))
+        }
+    }
+
+    /** Helper method for nested scroll connection */
+    fun consumeAvailableOffset(available: Offset): Offset {
+        val y = if (isRefreshing) 0f else {
+            val newOffset = (distancePulled + available.y).coerceAtLeast(0f)
+            val dragConsumed = newOffset - distancePulled
+            distancePulled = newOffset
+            _verticalOffset = calculateVerticalOffset()
+            dragConsumed
+        }
+        return Offset(0f, y)
+    }
+
+    /** Helper method for nested scroll connection. Calls onRefresh callback when triggered */
+    suspend fun onRelease(velocity: Float): Float {
+        if (isRefreshing) return 0f // Already refreshing, do nothing
+        // Trigger refresh
+        if (adjustedDistancePulled > positionalThreshold) {
+            startRefresh()
+        } else {
+            animateTo(0f)
+        }
+
+        val consumed = when {
+            // We are flinging without having dragged the pull refresh (for example a fling inside
+            // a list) - don't consume
+            distancePulled == 0f -> 0f
+            // If the velocity is negative, the fling is upwards, and we don't want to prevent the
+            // the list from scrolling
+            velocity < 0f -> 0f
+            // We are showing the indicator, and the fling is downwards - consume everything
+            else -> velocity
+        }
+        distancePulled = 0f
+        return consumed
+    }
+
+    suspend fun animateTo(offset: Float) {
+        animate(initialValue = _verticalOffset, targetValue = offset) { value, _ ->
+            _verticalOffset = value
+        }
+    }
+
+    /** Provides custom vertical offset behavior for [PullToRefreshContainer] */
+    fun calculateVerticalOffset(): Float = when {
+        // If drag hasn't gone past the threshold, the position is the adjustedDistancePulled.
+        adjustedDistancePulled <= positionalThreshold -> adjustedDistancePulled
+        else -> {
+            // How far beyond the threshold pull has gone, as a percentage of the threshold.
+            val overshootPercent = abs(progress) - 1.0f
+            // Limit the overshoot to 200%. Linear between 0 and 200.
+            val linearTension = overshootPercent.coerceIn(0f, 2f)
+            // Non-linear tension. Increases with linearTension, but at a decreasing rate.
+            val tensionPercent = linearTension - linearTension.pow(2) / 4
+            // The additional offset beyond the threshold.
+            val extraOffset = positionalThreshold * tensionPercent
+            positionalThreshold + extraOffset
+        }
+    }
+
+    companion object {
+        /** The default [Saver] for [PullToRefreshStateImpl]. */
+        fun Saver(
+            positionalThreshold: Float,
+            enabled: () -> Boolean,
+        ) = Saver<PullToRefreshState, Boolean>(
+            save = { it.isRefreshing },
+            restore = { isRefreshing ->
+                PullToRefreshStateImpl(isRefreshing, positionalThreshold, enabled)
+            }
+        )
+    }
+
+    internal var distancePulled by mutableFloatStateOf(0f)
+    private val adjustedDistancePulled: Float get() = distancePulled * DragMultiplier
+    private var _verticalOffset by mutableFloatStateOf(0f)
+    private var _refreshing by mutableStateOf(initialRefreshing)
+}
+
+/** The default pull indicator for [PullToRefreshContainer] */
+@Composable
+private fun CircularArrowProgressIndicator(
+    progress: () -> Float,
+    color: Color,
+) {
+    val path = remember { Path().apply { fillType = PathFillType.EvenOdd } }
+    // TODO: Consider refactoring this sub-component utilizing Modifier.Node
+    val targetAlpha by remember {
+        derivedStateOf { if (progress() >= 1f) MaxAlpha else MinAlpha }
+    }
+    val alphaState = animateFloatAsState(targetValue = targetAlpha, animationSpec = AlphaTween)
+    Canvas(
+        Modifier
+            .semantics(mergeDescendants = true) {
+                progressBarRangeInfo =
+                    ProgressBarRangeInfo(progress(), 0f..1f, 0)
+            }
+            .size(SpinnerSize)
+    ) {
+        val values = ArrowValues(progress())
+        val alpha = alphaState.value
+        rotate(degrees = values.rotation) {
+            val arcRadius = ArcRadius.toPx() + StrokeWidth.toPx() / 2f
+            val arcBounds = Rect(center = size.center, radius = arcRadius)
+            drawCircularIndicator(color, alpha, values, arcBounds, StrokeWidth)
+            drawArrow(path, arcBounds, color, alpha, values, StrokeWidth)
+        }
+    }
+}
+
+private fun DrawScope.drawCircularIndicator(
+    color: Color,
+    alpha: Float,
+    values: ArrowValues,
+    arcBounds: Rect,
+    strokeWidth: Dp
+) {
+    drawArc(
+        color = color,
+        alpha = alpha,
+        startAngle = values.startAngle,
+        sweepAngle = values.endAngle - values.startAngle,
+        useCenter = false,
+        topLeft = arcBounds.topLeft,
+        size = arcBounds.size,
+        style = Stroke(
+            width = strokeWidth.toPx(),
+            cap = StrokeCap.Square
+        )
+    )
+}
+
+@Immutable
+private class ArrowValues(
+    val rotation: Float,
+    val startAngle: Float,
+    val endAngle: Float,
+    val scale: Float
+)
+
+private fun ArrowValues(progress: Float): ArrowValues {
+    // Discard first 40% of progress. Scale remaining progress to full range between 0 and 100%.
+    val adjustedPercent = max(min(1f, progress) - 0.4f, 0f) * 5 / 3
+    // How far beyond the threshold pull has gone, as a percentage of the threshold.
+    val overshootPercent = abs(progress) - 1.0f
+    // Limit the overshoot to 200%. Linear between 0 and 200.
+    val linearTension = overshootPercent.coerceIn(0f, 2f)
+    // Non-linear tension. Increases with linearTension, but at a decreasing rate.
+    val tensionPercent = linearTension - linearTension.pow(2) / 4
+
+    // Calculations based on SwipeRefreshLayout specification.
+    val endTrim = adjustedPercent * MaxProgressArc
+    val rotation = (-0.25f + 0.4f * adjustedPercent + tensionPercent) * 0.5f
+    val startAngle = rotation * 360
+    val endAngle = (rotation + endTrim) * 360
+    val scale = min(1f, adjustedPercent)
+
+    return ArrowValues(rotation, startAngle, endAngle, scale)
+}
+
+private fun DrawScope.drawArrow(
+    arrow: Path,
+    bounds: Rect,
+    color: Color,
+    alpha: Float,
+    values: ArrowValues,
+    strokeWidth: Dp,
+) {
+    arrow.reset()
+    arrow.moveTo(0f, 0f) // Move to left corner
+    arrow.lineTo(x = ArrowWidth.toPx() * values.scale, y = 0f) // Line to right corner
+
+    // Line to tip of arrow
+    arrow.lineTo(
+        x = ArrowWidth.toPx() * values.scale / 2,
+        y = ArrowHeight.toPx() * values.scale
+    )
+
+    val radius = min(bounds.width, bounds.height) / 2f
+    val inset = ArrowWidth.toPx() * values.scale / 2f
+    arrow.translate(
+        Offset(
+            x = radius + bounds.center.x - inset,
+            y = bounds.center.y + strokeWidth.toPx() / 2f
+        )
+    )
+    arrow.close()
+    rotate(degrees = values.endAngle) {
+        drawPath(path = arrow, color = color, alpha = alpha)
+    }
+}
+
+private const val MaxProgressArc = 0.8f
+private const val CrossfadeDurationMs = MotionTokens.DurationShort2.toInt()
+
+/** The default stroke width for [Indicator] */
+private val StrokeWidth = 2.5.dp
+private val ArcRadius = 7.5.dp
+private val SpinnerSize = 20.dp // (ArcRadius + PullRefreshIndicatorDefaults.StrokeWidth).times(2)
+private val Elevation = ElevationTokens.Level2
+private val ArrowWidth = 10.dp
+private val ArrowHeight = 5.dp
+
+// Values taken from SwipeRefreshLayout
+private const val MinAlpha = 0.3f
+private const val MaxAlpha = 1f
+private val AlphaTween = tween<Float>(MotionTokens.DurationMedium2.toInt(), easing = LinearEasing)
+
+/**
+ * The distance pulled is multiplied by this value to give us the adjusted distance pulled, which
+ * is used in calculating the indicator position (when the adjusted distance pulled is less than
+ * the refresh threshold, it is the indicator position, otherwise the indicator position is
+ * derived from the progress).
+ */
+private const val DragMultiplier = 0.5f
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/animation/AnimatorTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/animation/AnimatorTest.kt
index 148e864..b9e2e05 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/animation/AnimatorTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/animation/AnimatorTest.kt
@@ -22,7 +22,6 @@
 import androidx.test.annotation.UiThreadTest
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import org.junit.Assert.assertTrue
 import org.junit.Before
@@ -82,7 +81,6 @@
     }
 
     @UiThreadTest
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testDoOnPause() {
         var called = false
         animator.doOnPause {
@@ -98,7 +96,6 @@
     }
 
     @UiThreadTest
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testDoOnResume() {
         var called = false
         animator.doOnResume {
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/graphics/PathTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/graphics/PathTest.kt
index c09ed29..630eee4 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/graphics/PathTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/graphics/PathTest.kt
@@ -52,7 +52,6 @@
         assertEquals(3, count)
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testUnion() {
         val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) }
         val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) }
@@ -64,7 +63,6 @@
         assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r)
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testOr() {
         val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) }
         val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) }
@@ -76,7 +74,6 @@
         assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r)
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testDifference() {
         val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) }
         val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) }
@@ -88,7 +85,6 @@
         assertEquals(RectF(0.0f, 0.0f, 5.0f, 10.0f), r)
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testIntersection() {
         val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) }
         val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) }
@@ -100,7 +96,6 @@
         assertEquals(RectF(5.0f, 0.0f, 10.0f, 10.0f), r)
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testEmptyIntersection() {
         val r1 = Path().apply { addRect(0.0f, 0.0f, 2.0f, 2.0f, Path.Direction.CW) }
         val r2 = Path().apply { addRect(5.0f, 5.0f, 7.0f, 7.0f, Path.Direction.CW) }
@@ -109,7 +104,6 @@
         assertTrue(p.isEmpty)
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test fun testXor() {
         val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) }
         val r2 = Path().apply { addRect(5.0f, 5.0f, 15.0f, 15.0f, Path.Direction.CW) }
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/os/BundleTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/os/BundleTest.kt
index a1af056..564ab34 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/os/BundleTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/os/BundleTest.kt
@@ -44,6 +44,7 @@
         val charSequenceValue = "hey"
         val parcelableValue = Rect(1, 2, 3, 4)
         val serializableValue = AtomicInteger(1)
+        val binderValue = object : IBinder by Binder() {}
 
         val bundle = bundleOf(
             "null" to null,
@@ -60,6 +61,7 @@
             "bundle" to bundleValue,
             "charSequence" to charSequenceValue,
             "parcelable" to parcelableValue,
+            "binder" to binderValue,
 
             "booleanArray" to booleanArrayOf(),
             "byteArray" to byteArrayOf(),
@@ -78,7 +80,7 @@
             "serializable" to serializableValue
         )
 
-        assertEquals(25, bundle.size())
+        assertEquals(26, bundle.size())
 
         assertNull(bundle["null"])
 
@@ -94,6 +96,7 @@
         assertSame(bundleValue, bundle["bundle"])
         assertSame(charSequenceValue, bundle["charSequence"])
         assertSame(parcelableValue, bundle["parcelable"])
+        assertSame(binderValue, bundle["binder"])
 
         assertArrayEquals(booleanArrayOf(), bundle["booleanArray"] as BooleanArray)
         assertArrayEquals(byteArrayOf(), bundle["byteArray"] as ByteArray)
@@ -113,14 +116,6 @@
         assertSame(serializableValue, bundle["serializable"])
     }
 
-    @SdkSuppress(minSdkVersion = 18)
-    @Suppress("DEPRECATION")
-    @Test fun bundleOfValidApi18() {
-        val binderValue = object : IBinder by Binder() {}
-        val bundle = bundleOf("binder" to binderValue)
-        assertSame(binderValue, bundle["binder"])
-    }
-
     @SdkSuppress(minSdkVersion = 21)
     @Suppress("DEPRECATION")
     @Test fun bundleOfValidApi21() {
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt
index 4abd56a..808c4c8 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/transition/TransitionTest.kt
@@ -25,7 +25,6 @@
 import androidx.core.TestActivity
 import androidx.core.ktx.test.R
 import androidx.test.filters.MediumTest
-import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
@@ -35,7 +34,6 @@
 import org.junit.Rule
 import org.junit.Test
 
-@SdkSuppress(minSdkVersion = 19)
 @MediumTest
 class TransitionTest {
     @Suppress("DEPRECATION")
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/util/AtomicFileTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/util/AtomicFileTest.kt
index 9101f82..56ef15c 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/util/AtomicFileTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/util/AtomicFileTest.kt
@@ -17,7 +17,6 @@
 package androidx.core.util
 
 import android.util.AtomicFile
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.testutils.assertThrows
 import java.io.IOException
@@ -28,7 +27,6 @@
 import org.junit.Test
 import org.junit.rules.TemporaryFolder
 
-@SdkSuppress(minSdkVersion = 17)
 @SmallTest
 class AtomicFileTest {
     @get:Rule val temporaryFolder = TemporaryFolder()
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/util/LongSparseArrayTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/util/LongSparseArrayTest.kt
index 6fe69fe..2112ebf 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/util/LongSparseArrayTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/util/LongSparseArrayTest.kt
@@ -17,7 +17,6 @@
 package androidx.core.util
 
 import android.util.LongSparseArray
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.testutils.fail
 import com.google.common.truth.Truth.assertThat
@@ -27,7 +26,6 @@
 import org.junit.Assert.assertTrue
 import org.junit.Test
 
-@SdkSuppress(minSdkVersion = 16)
 @SmallTest
 class LongSparseArrayTest {
     @Test fun sizeProperty() {
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/util/SparseLongArrayTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/util/SparseLongArrayTest.kt
index 84fd6e4..33cecad 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/util/SparseLongArrayTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/util/SparseLongArrayTest.kt
@@ -17,7 +17,6 @@
 package androidx.core.util
 
 import android.util.SparseLongArray
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.testutils.fail
 import com.google.common.truth.Truth.assertThat
@@ -26,7 +25,6 @@
 import org.junit.Assert.assertTrue
 import org.junit.Test
 
-@SdkSuppress(minSdkVersion = 18)
 @SmallTest
 class SparseLongArrayTest {
     @Test fun sizeProperty() {
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/view/ViewGroupTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/view/ViewGroupTest.kt
index cb3a05d..48504a8 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/view/ViewGroupTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/view/ViewGroupTest.kt
@@ -20,7 +20,6 @@
 import android.view.ViewGroup
 import android.widget.LinearLayout
 import androidx.test.core.app.ApplicationProvider
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.testutils.assertThrows
 import androidx.testutils.fail
@@ -346,7 +345,6 @@
         assertEquals(40, layoutParams.bottomMargin)
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test fun updateMarginsRelative() {
         val layoutParams = ViewGroup.MarginLayoutParams(100, 200)
         layoutParams.updateMarginsRelative(start = 10, end = 20)
@@ -359,7 +357,6 @@
         assertTrue(layoutParams.isMarginRelative)
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test fun updateMarginsRelativeNoOp() {
         val layoutParams = ViewGroup.MarginLayoutParams(100, 200)
         layoutParams.setMargins(10, 20, 30, 40)
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/view/ViewTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/view/ViewTest.kt
index 1dc87bb..1145b1d 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/view/ViewTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/view/ViewTest.kt
@@ -25,7 +25,6 @@
 import android.widget.RelativeLayout
 import androidx.core.ktx.test.R
 import androidx.test.core.app.ApplicationProvider
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.testutils.assertThrows
 import androidx.testutils.fail
@@ -138,7 +137,6 @@
         assertEquals(40, view.paddingBottom)
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     fun updatePaddingRelative() {
         view.updatePaddingRelative(start = 10, end = 20)
@@ -148,7 +146,6 @@
         assertEquals(0, view.paddingBottom)
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     fun updatePaddingRelativeNoOp() {
         view.setPaddingRelative(10, 20, 30, 40)
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/CallCompatTest.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/CallCompatTest.kt
index 42e18a6..362672c 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/CallCompatTest.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/CallCompatTest.kt
@@ -25,6 +25,12 @@
 import androidx.core.telecom.CallAttributesCompat
 import androidx.core.telecom.CallControlResult
 import androidx.core.telecom.CallsManager
+import androidx.core.telecom.extensions.Capability
+import androidx.core.telecom.extensions.CapabilityExchange
+import androidx.core.telecom.extensions.ParticipantClientActionsImpl
+import androidx.core.telecom.extensions.voip.CapabilityExchangeListener
+import androidx.core.telecom.extensions.voip.VoipExtensionManager
+import androidx.core.telecom.internal.CallChannels
 import androidx.core.telecom.internal.CallCompat
 import androidx.core.telecom.internal.InCallServiceCompat
 import androidx.core.telecom.internal.utils.Utils
@@ -42,6 +48,7 @@
 import org.junit.After
 import org.junit.Assert
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -63,7 +70,6 @@
 @RunWith(AndroidJUnit4::class)
 class CallCompatTest : BaseTelecomTest() {
     private lateinit var callCompat: CallCompat
-    private lateinit var inCallServiceCompat: InCallServiceCompat
     private var mScope: CoroutineScope = CoroutineScope(Dispatchers.IO)
 
     /**
@@ -79,12 +85,12 @@
          * Logging for within the test class.
          */
         internal val TAG = CallCompatTest::class.simpleName
+        private const val ICS_TEST_ID = 1
     }
 
     @Before
     fun setUp() {
         Utils.resetUtils()
-        inCallServiceCompat = InCallServiceCompat()
     }
 
     @After
@@ -93,58 +99,7 @@
     }
 
     /**
-     * Assert that EXTRAS is the extension type for calls made using the V1.5 ConnectionService +
-     * Extensions Library (Auto). The call should have the [CallsManager.EXTRA_VOIP_API_VERSION]
-     * defined in the extras.
-     *
-     * The contents of the call detail extras need to be modified to test calls using the V1.5
-     * ConnectionService + Extensions library (until E2E testing can be supported for it). This
-     * requires us to manually insert the [CallsManager.EXTRA_VOIP_API_VERSION] key into the bundle.
-     *
-     * Note: This portion of the logic in [InCallServiceCompat.onCallAdded] is not yet supported so
-     * for this test, we just configure the call and directly invoke
-     * [CallCompat.resolveCallExtensionsType] ensuring that it returns EXTRAS properly.
-     */
-    @LargeTest
-    @Test(timeout = 10000)
-    fun testResolveCallExtension_Extra() {
-        setUpBackwardsCompatTest()
-        val voipApiExtra = Pair(CallsManager.EXTRA_VOIP_API_VERSION, true)
-        addAndVerifyCallExtensionType(
-            TestUtils.OUTGOING_CALL_ATTRIBUTES,
-            CallCompat.EXTRAS,
-            extraToInclude = voipApiExtra)
-    }
-
-    /**
-     * Assert that CAPABILITY_EXCHANGE is the extension type for calls that either have the
-     * [CallsManager.PROPERTY_IS_TRANSACTIONAL] (V) defined as a property or the phone account
-     * supports transactional ops (U+) and that capability exchange between the VOIP app and
-     * associated ICS is successful. This is signaled from the ICS side when the feature setup is
-     * completed via CapabilityExchange#featureSetupComplete.
-     *
-     * For pre-U devices, the call extras would define the
-     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] key.
-     *
-     * Note: The version codes for V is not available so we need to enforce a strict manual check
-     * to ensure the V test path is not executed by incompatible devices.
-     */
-    @LargeTest
-    @Test(timeout = 10000)
-    fun testResolveCallExtension_CapabilityExchange() {
-        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
-        val backwardsCompatExtra = configureCapabilityExchangeTypeTest()
-        addAndVerifyCallExtensionType(
-            TestUtils.OUTGOING_CALL_ATTRIBUTES,
-            CallCompat.CAPABILITY_EXCHANGE,
-            // Waiting is not required for U+ testing
-            waitForCallDetailExtras = !TestUtils.buildIsAtLeastU(),
-            extraToInclude = backwardsCompatExtra,
-        )
-    }
-
-    /**
-     * Assert that for calls supporting [CallCompat.CAPABILITY_EXCHANGE] that capability
+     * Assert that for calls supporting [InCallServiceCompat.CAPABILITY_EXCHANGE] that capability
      * exchange between the VOIP app and associated ICS is successful. This is signaled from the
      * ICS side when the feature setup is completed via CapabilityExchange#featureSetupComplete.
      *
@@ -165,31 +120,123 @@
     }
 
     /**
-     * Assert that NONE is the extension type for calls with phone accounts that do not support
-     * transactional ops and that capability exchange does not succeed in this case. Note that the
-     * caller must have had the read phone numbers permission.
-     *
-     * Note: Ensure that all extras are cleared before asserting extension type so that the phone
-     * account can be checked. For backwards compatibility tests, calls define the
-     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] key in the details extras so this
-     * needs to be disregarded.
-     *
-     * We need to ensure that all extras/properties are ignored for testing so that the phone
-     * account can be checked to see if it supports transactional ops. In jetpack, this can only be
-     * verified on pre-U devices as those phone accounts are registered in Telecom without
-     * transactional ops. Keep in mind that because these calls are set up for backwards
-     * compatibility, they will have the [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED]
-     * extra in the details (which will need to be ignored during testing).
+     * In the case that the ICS and VOIP apps both support the Participant [Capability],
+     * [CallsManager.KICK_PARTICIPANT_ACTION], and [CallsManager.RAISE_HAND_ACTION] this test
+     * asserts that [CallCompat.setupSupportedCapabilities] successfully sets
+     * [ParticipantClientActionsImpl.mIsParticipantExtensionSupported] to true and populates
+     * [ParticipantClientActionsImpl.mNegotiatedActions] with both supported actions.
      */
     @LargeTest
     @Test(timeout = 10000)
-    fun testResolveCallExtension_TransactionalOpsNotSupported() {
-        // Phone accounts that don't use the v2 APIs don't support transactional ops.
-        setUpBackwardsCompatTest()
-        addAndVerifyCallExtensionType(
+    fun testCompareSupportedCaps_ParticipantSupportedFully() {
+        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
+        val backwardsCompatExtra = configureCapabilityExchangeTypeTest()
+
+        val icsParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.RAISE_HAND_ACTION, CallsManager.KICK_PARTICIPANT_ACTION)
+        val voipParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.RAISE_HAND_ACTION, CallsManager.KICK_PARTICIPANT_ACTION)
+        val expectedNegotiatedActions = intArrayOf(CallsManager.RAISE_HAND_ACTION,
+            CallsManager.KICK_PARTICIPANT_ACTION)
+
+        verifyCompareSupportedCapabilitiesSuccessful(
             TestUtils.OUTGOING_CALL_ATTRIBUTES,
-            CallCompat.NONE,
-            waitForCallDetailExtras = false
+            // Waiting is not required for U+ testing
+            waitForCallDetailExtras = !TestUtils.buildIsAtLeastU(),
+            extraToInclude = backwardsCompatExtra,
+            icsCap = icsParticipantCap,
+            voipCap = voipParticipantCap,
+            expectedIsParticipantExtensionSupported = true,
+            expectedNegotiatedActions = expectedNegotiatedActions
+        )
+    }
+
+    /**
+     * In the case that the ICS and VOIP apps both support the Participant [Capability]
+     * but only [CallsManager.RAISE_HAND_ACTION], this test asserts that
+     * [CallCompat.setupSupportedCapabilities] successfully sets
+     * [ParticipantClientActionsImpl.mIsParticipantExtensionSupported] to true and populates
+     * [ParticipantClientActionsImpl.mNegotiatedActions] with the supported action.
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testCompareSupportedCaps_ParticipantRaiseHandSupportOnly() {
+        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
+        val backwardsCompatExtra = configureCapabilityExchangeTypeTest()
+
+        val icsParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.RAISE_HAND_ACTION)
+        val voipParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.RAISE_HAND_ACTION)
+        val expectedNegotiatedActions = intArrayOf(CallsManager.RAISE_HAND_ACTION)
+
+        verifyCompareSupportedCapabilitiesSuccessful(
+            TestUtils.OUTGOING_CALL_ATTRIBUTES,
+            // Waiting is not required for U+ testing
+            waitForCallDetailExtras = !TestUtils.buildIsAtLeastU(),
+            extraToInclude = backwardsCompatExtra,
+            icsCap = icsParticipantCap,
+            voipCap = voipParticipantCap,
+            expectedIsParticipantExtensionSupported = true,
+            expectedNegotiatedActions = expectedNegotiatedActions
+        )
+    }
+
+    /**
+     * In the case that the ICS and VOIP apps both support the Participant [Capability]
+     * but none of the same actions, this test asserts that
+     * [CallCompat.setupSupportedCapabilities] successfully sets
+     * [ParticipantClientActionsImpl.mIsParticipantExtensionSupported] to true and leaves
+     * [ParticipantClientActionsImpl.mNegotiatedActions] empty.
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testCompareSupportedCaps_ParticipantSupportedEmptyNegotiatedActions() {
+        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
+        val backwardsCompatExtra = configureCapabilityExchangeTypeTest()
+
+        val icsParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.KICK_PARTICIPANT_ACTION)
+        val voipParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.RAISE_HAND_ACTION)
+
+        verifyCompareSupportedCapabilitiesSuccessful(
+            TestUtils.OUTGOING_CALL_ATTRIBUTES,
+            // Waiting is not required for U+ testing
+            waitForCallDetailExtras = !TestUtils.buildIsAtLeastU(),
+            extraToInclude = backwardsCompatExtra,
+            icsCap = icsParticipantCap,
+            voipCap = voipParticipantCap,
+            expectedIsParticipantExtensionSupported = true,
+            expectedNegotiatedActions = IntArray(0)
+        )
+    }
+
+    /**
+     * In the case that the ICS app supports the Participant [Capability] but the VoIP app doesn't,
+     * this test asserts that [CallCompat.setupSupportedCapabilities] successfully sets
+     * [ParticipantClientActionsImpl.mIsParticipantExtensionSupported] to false and leaves
+     * [ParticipantClientActionsImpl.mNegotiatedActions] empty.
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testCompareSupportedCaps_IcsSupportsParticipantVoipDoesNot() {
+        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
+        val backwardsCompatExtra = configureCapabilityExchangeTypeTest()
+
+        val icsParticipantCap = initializeCapability(CallsManager.PARTICIPANT,
+            CallsManager.KICK_PARTICIPANT_ACTION)
+        val voipCallSilenceCap = initializeCapability(CallsManager.CALL_SILENCE)
+
+        verifyCompareSupportedCapabilitiesSuccessful(
+            TestUtils.OUTGOING_CALL_ATTRIBUTES,
+            // Waiting is not required for U+ testing
+            waitForCallDetailExtras = !TestUtils.buildIsAtLeastU(),
+            extraToInclude = backwardsCompatExtra,
+            icsCap = icsParticipantCap,
+            voipCap = voipCallSilenceCap,
+            expectedIsParticipantExtensionSupported = false,
+            expectedNegotiatedActions = IntArray(0)
         )
     }
 
@@ -198,55 +245,9 @@
      *********************************************************************************************/
 
     /**
-     * Helper to add a call via CallsManager#addCall and verify the extension type depending on
-     * the APIs that are leveraged.
-     *
-     * Note: The connection extras are not added into the call until the connection is successfully
-     * created. This is usually the case when the call moves from the CONNECTING state into either
-     * the DIALING/RINGING state. This would be the case for [CallsManager.EXTRA_VOIP_API_VERSION]
-     * (handled by auto) as well as for [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED]
-     * (see JetpackConnectionService#createSelfManagedConnection). Keep in mind that these extras
-     * would not be available in [InCalLService#onCallAdded], but after
-     * [Call#handleCreateConnectionSuccess] is invoked and the connection service extras are
-     * propagated into the call details via [Call#putConnectionServiceExtras].
-     *
-     * @param callAttributesCompat for the call.
-     * @param expectedType for call extension type.
-     * @param waitForCallDetailExtras used for waiting on the call details extras to be non-null.
-     * @param extraToInclude as part of the call extras.
-     */
-    private fun addAndVerifyCallExtensionType(
-        callAttributesCompat: CallAttributesCompat,
-        @CallCompat.Companion.CapabilityExchangeType expectedType: Int,
-        waitForCallDetailExtras: Boolean = true,
-        extraToInclude: Pair<String, Boolean>? = null
-    ) {
-        runBlocking {
-            assertWithinTimeout_addCall(callAttributesCompat) {
-                launch {
-                    try {
-                        // Enforce waiting logic to ensure that the call details extras are populated.
-                        val call = configureCallWithSanitizedExtras(
-                            waitForCallDetailExtras, extraToInclude)
-
-                        callCompat = CallCompat(call, mContext, mScope, inCallServiceCompat)
-                        // Assert call extension type.
-                        assertEquals(expectedType, callCompat.resolveCallExtensionsType(call))
-                    } finally {
-                        // Always send disconnect signal if possible.
-                        assertEquals(
-                            CallControlResult.Success(),
-                            disconnect(DisconnectCause(DisconnectCause.LOCAL)))
-                    }
-                }
-            }
-        }
-    }
-
-    /**
      * Helper to add a call via CallsManager#addCall and verify that the capabilities are properly
      * negotiated between the VOIP app and ICS's given that the ICS supports the exchange
-     * ([CallCompat.CAPABILITY_EXCHANGE]).
+     * ([InCallServiceCompat.CAPABILITY_EXCHANGE]).
      *
      * @param callAttributesCompat for the call.
      * @param waitForCallDetailExtras used for waiting on the call details extras to be non-null.
@@ -265,10 +266,11 @@
                         val call = configureCallWithSanitizedExtras(
                             waitForCallDetailExtras, extraToInclude)
 
-                        callCompat = CallCompat(call, mContext, mScope, inCallServiceCompat)
+                        callCompat = CallCompat(call, mScope)
 
                         mScope.async {
-                            Assert.assertTrue(callCompat.initiateICSCapabilityExchange(call))
+                            callCompat.startCapabilityExchange()
+                            Assert.assertTrue(callCompat.capExchangeSetupComplete)
                         }.await()
                     } finally {
                         // Always send disconnect signal if possible.
@@ -282,6 +284,92 @@
     }
 
     /**
+     * Helper to verify that the capabilities are properly compared between the VOIP app and ICS's
+     * given that the ICS supports the exchange ([InCallServiceCompat.CAPABILITY_EXCHANGE]).
+     *
+     * @param callAttributesCompat for the call.
+     * @param waitForCallDetailExtras used for waiting on the call details extras to be non-null.
+     * @param extraToInclude as part of the call extras.
+     * @param icsCap the Capability that the ICS app supports.
+     * @param voipCap the Capability that the VoIP app supports.
+     * @param expectedIsParticipantExtensionSupported based the icsCap and voipCap configurations.
+     * @param expectedNegotiatedActions the common actions that are supported by both ICS and VoIP.
+     */
+    // Todo: Expand this helper method to support verifying multiple capabilities per voip/ics app.
+    private fun verifyCompareSupportedCapabilitiesSuccessful(
+        callAttributesCompat: CallAttributesCompat,
+        waitForCallDetailExtras: Boolean = true,
+        extraToInclude: Pair<String, Boolean>? = null,
+        icsCap: Capability,
+        voipCap: Capability,
+        expectedIsParticipantExtensionSupported: Boolean,
+        expectedNegotiatedActions: IntArray
+    ) {
+        runBlocking {
+            assertWithinTimeout_addCall(callAttributesCompat) {
+                launch {
+                    try {
+                        // Enforce waiting logic to ensure that call details extras are populated.
+                        val call = configureCallWithSanitizedExtras(
+                            waitForCallDetailExtras, extraToInclude)
+
+                        // Setup the CapExchange and CallCompat instances for testing:
+                        val voipCaps: MutableList<Capability> = mutableListOf(voipCap)
+                        val capExchange = createCapExchange(voipCaps)
+                        callCompat = CallCompat(call, mScope)
+                        callCompat.icsCapabilities.add(icsCap)
+                        callCompat.addExtension { }
+
+                        // Directly invoke the helper method that handles capability comparison:
+                        callCompat.setupSupportedCapabilities(capExchange)
+
+                        // Check all expected values:
+                        val participantListener = callCompat.participantStateListener
+                        assertEquals(participantListener.mIsParticipantExtensionSupported,
+                            expectedIsParticipantExtensionSupported)
+                        assertEquals(participantListener.mNegotiatedActions.size,
+                            expectedNegotiatedActions.size)
+                        for (action in expectedNegotiatedActions) {
+                            assertTrue(participantListener.mNegotiatedActions.contains(action))
+                        }
+                    } finally {
+                        // Always send disconnect signal if possible.
+                        assertEquals(
+                            CallControlResult.Success(),
+                            disconnect(DisconnectCause(DisconnectCause.LOCAL)))
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Helper to initialize and populate an instance of [Capability] for unit testing purposes.
+     */
+    private fun initializeCapability(featureId: Int, vararg actions: Int): Capability {
+        val cap = Capability()
+        cap.featureId = featureId
+        cap.featureVersion = 1
+        cap.supportedActions = actions
+        return cap
+    }
+
+    /**
+     * Helper to initialize and populate an instance of [CapabilityExchange] for unit testing purposes.
+     */
+    private fun createCapExchange(voipCaps: MutableList<Capability>): CapabilityExchange {
+        val capExchange = CapabilityExchange()
+        val callChannels = CallChannels()
+        val emptyExtensions = emptyList<Capability>()
+        val voipExtensionManager =
+            VoipExtensionManager(mContext, mWorkerContext, callChannels, emptyExtensions)
+        val capExchangeListener = CapabilityExchangeListener(voipExtensionManager, ICS_TEST_ID)
+        capExchange.voipCapabilities = voipCaps
+        capExchange.capabilityExchangeListener = capExchangeListener
+        return capExchange
+    }
+
+    /**
      * Helper to retrieve the call from MockInCallService and wait for any call detail extras
      * to be populated, if needed.
      */
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2ECallExtensionExtrasTests.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2ECallExtensionExtrasTests.kt
index 7a9e27a..516dfad 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2ECallExtensionExtrasTests.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/E2ECallExtensionExtrasTests.kt
@@ -24,9 +24,10 @@
 import androidx.core.telecom.CallAttributesCompat
 import androidx.core.telecom.CallControlResult
 import androidx.core.telecom.CallsManager
-import androidx.core.telecom.internal.CallCompat
+import androidx.core.telecom.internal.InCallServiceCompat
 import androidx.core.telecom.internal.utils.Utils
 import androidx.core.telecom.test.utils.BaseTelecomTest
+import androidx.core.telecom.test.utils.MockInCallService
 import androidx.core.telecom.test.utils.TestUtils
 import androidx.core.telecom.test.utils.TestUtils.waitOnInCallServiceToReachXCallCompats
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -198,12 +199,12 @@
             if (TestUtils.buildIsAtLeastV()) {
                 assertTrue(callDetails.hasProperty(CallsManager.PROPERTY_IS_TRANSACTIONAL))
             } else if (Utils.hasPlatformV2Apis()) {
-                var callCompat: CallCompat?
                 // Wait for capability exchange to complete before verifying the extension level:
                 runBlocking {
-                    callCompat = waitOnInCallServiceToReachXCallCompats(1)
+                    waitOnInCallServiceToReachXCallCompats(1)
                 }
-                assertEquals(CallCompat.CAPABILITY_EXCHANGE, callCompat?.mExtensionLevelSupport)
+                 assertEquals(InCallServiceCompat.CAPABILITY_EXCHANGE,
+                     MockInCallService.getService()?.mExtensionLevelSupport)
             }
         } else {
             val containsBackwardsCompatKey = callDetails.extras != null && callDetails.extras
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/InCallServiceCompatTest.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/InCallServiceCompatTest.kt
new file mode 100644
index 0000000..4e9748e
--- /dev/null
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/InCallServiceCompatTest.kt
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2023 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.core.telecom.test
+
+import android.Manifest
+import android.os.Build
+import android.telecom.Call
+import android.telecom.DisconnectCause
+import android.util.Log
+import androidx.annotation.RequiresApi
+import androidx.core.telecom.CallAttributesCompat
+import androidx.core.telecom.CallControlResult
+import androidx.core.telecom.CallsManager
+import androidx.core.telecom.internal.InCallServiceCompat
+import androidx.core.telecom.internal.utils.Utils
+import androidx.core.telecom.test.utils.BaseTelecomTest
+import androidx.core.telecom.test.utils.MockInCallService
+import androidx.core.telecom.test.utils.TestUtils
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.rule.GrantPermissionRule
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * This test class can be used to verify the [InCallServiceCompat] functionality.
+ *
+ * Note: [Call] is package-private so we still need to leverage Telecom to create calls on our
+ * behalf for testing. The call properties and extras fields aren't mutable so we need to ensure
+ * that we wait for them to become available before accessing them.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@RequiresApi(Build.VERSION_CODES.O)
+@RunWith(AndroidJUnit4::class)
+class InCallServiceCompatTest : BaseTelecomTest() {
+    private lateinit var inCallServiceCompat: InCallServiceCompat
+
+    /**
+     * Grant READ_PHONE_NUMBERS permission as part of testing
+     * [InCallServiceCompat#resolveCallExtensionsType].
+     */
+    @get:Rule
+    val readPhoneNumbersRule: GrantPermissionRule =
+        GrantPermissionRule.grant(Manifest.permission.READ_PHONE_NUMBERS)!!
+
+    companion object {
+        /**
+         * Logging for within the test class.
+         */
+        internal val TAG = InCallServiceCompatTest::class.simpleName
+    }
+
+    @Before
+    fun setUp() {
+        Utils.resetUtils()
+        inCallServiceCompat = InCallServiceCompat()
+    }
+
+    @After
+    fun onDestroy() {
+        Utils.resetUtils()
+    }
+
+    /**
+     * Assert that EXTRAS is the extension type for calls made using the V1.5 ConnectionService +
+     * Extensions Library (Auto). The call should have the [CallsManager.EXTRA_VOIP_API_VERSION]
+     * defined in the extras.
+     *
+     * The contents of the call detail extras need to be modified to test calls using the V1.5
+     * ConnectionService + Extensions library (until E2E testing can be supported for it). This
+     * requires us to manually insert the [CallsManager.EXTRA_VOIP_API_VERSION] key into the bundle.
+     *
+     * Note: This portion of the logic in [InCallServiceCompat.onCallAdded] is not yet supported so
+     * for this test, we just configure the call and directly invoke
+     * [InCallServiceCompat.resolveCallExtensionsType] ensuring that it returns EXTRAS properly.
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testResolveCallExtension_Extra() {
+        setUpBackwardsCompatTest()
+        val voipApiExtra = Pair(CallsManager.EXTRA_VOIP_API_VERSION, true)
+        addAndVerifyCallExtensionType(
+            TestUtils.OUTGOING_CALL_ATTRIBUTES,
+            InCallServiceCompat.EXTRAS,
+            extraToInclude = voipApiExtra)
+    }
+
+    /**
+     * Assert that CAPABILITY_EXCHANGE is the extension type for calls that either have the
+     * [CallsManager.PROPERTY_IS_TRANSACTIONAL] (V) defined as a property or the phone account
+     * supports transactional ops (U+) and that capability exchange between the VOIP app and
+     * associated ICS is successful. This is signaled from the ICS side when the feature setup is
+     * completed via CapabilityExchange#featureSetupComplete.
+     *
+     * For pre-U devices, the call extras would define the
+     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] key.
+     *
+     * Note: The version codes for V is not available so we need to enforce a strict manual check
+     * to ensure the V test path is not executed by incompatible devices.
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testResolveCallExtension_CapabilityExchange() {
+        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
+        val backwardsCompatExtra = configureCapabilityExchangeTypeTest()
+        addAndVerifyCallExtensionType(
+            TestUtils.OUTGOING_CALL_ATTRIBUTES,
+            InCallServiceCompat.CAPABILITY_EXCHANGE,
+            // Waiting is not required for U+ testing
+            waitForCallDetailExtras = !TestUtils.buildIsAtLeastU(),
+            extraToInclude = backwardsCompatExtra,
+        )
+    }
+
+    /**
+     * Assert that NONE is the extension type for calls with phone accounts that do not support
+     * transactional ops and that capability exchange does not succeed in this case. Note that the
+     * caller must have had the read phone numbers permission.
+     *
+     * Note: Ensure that all extras are cleared before asserting extension type so that the phone
+     * account can be checked. For backwards compatibility tests, calls define the
+     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] key in the details extras so this
+     * needs to be disregarded.
+     *
+     * We need to ensure that all extras/properties are ignored for testing so that the phone
+     * account can be checked to see if it supports transactional ops. In jetpack, this can only be
+     * verified on pre-U devices as those phone accounts are registered in Telecom without
+     * transactional ops. Keep in mind that because these calls are set up for backwards
+     * compatibility, they will have the [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED]
+     * extra in the details (which will need to be ignored during testing).
+     */
+    @LargeTest
+    @Test(timeout = 10000)
+    fun testResolveCallExtension_TransactionalOpsNotSupported() {
+        // Phone accounts that don't use the v2 APIs don't support transactional ops.
+        setUpBackwardsCompatTest()
+        addAndVerifyCallExtensionType(
+            TestUtils.OUTGOING_CALL_ATTRIBUTES,
+            InCallServiceCompat.NONE,
+            waitForCallDetailExtras = true
+        )
+    }
+
+    /***********************************************************************************************
+     *                           Helpers
+     *********************************************************************************************/
+
+    /**
+     * Helper to add a call via CallsManager#addCall and verify the extension type depending on
+     * the APIs that are leveraged.
+     *
+     * Note: The connection extras are not added into the call until the connection is successfully
+     * created. This is usually the case when the call moves from the CONNECTING state into either
+     * the DIALING/RINGING state. This would be the case for [CallsManager.EXTRA_VOIP_API_VERSION]
+     * (handled by auto) as well as for [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED]
+     * (see JetpackConnectionService#createSelfManagedConnection). Keep in mind that these extras
+     * would not be available in [InCalLService#onCallAdded], but after
+     * [Call#handleCreateConnectionSuccess] is invoked and the connection service extras are
+     * propagated into the call details via [Call#putConnectionServiceExtras].
+     *
+     * @param callAttributesCompat for the call.
+     * @param expectedType for call extension type.
+     * @param waitForCallDetailExtras used for waiting on the call details extras to be non-null.
+     * @param extraToInclude as part of the call extras.
+     */
+    private fun addAndVerifyCallExtensionType(
+        callAttributesCompat: CallAttributesCompat,
+        @InCallServiceCompat.Companion.CapabilityExchangeType expectedType: Int,
+        waitForCallDetailExtras: Boolean = true,
+        extraToInclude: Pair<String, Boolean>? = null
+    ) {
+        runBlocking {
+            assertWithinTimeout_addCall(callAttributesCompat) {
+                launch {
+                    try {
+                        // Enforce waiting logic to ensure that the call details extras are populated.
+                        val call = configureCallWithSanitizedExtras(
+                            waitForCallDetailExtras, extraToInclude)
+
+                        Log.i(TAG, "Service bounded invoking resolveCallExtensionsType")
+
+                        // Assert call extension type.
+                        val ics = MockInCallService.getService()
+                        Assert.assertEquals(expectedType, ics?.resolveCallExtensionsType(call))
+                    } finally {
+                        // Always send disconnect signal if possible.
+                        Assert.assertEquals(
+                            CallControlResult.Success(),
+                            disconnect(DisconnectCause(DisconnectCause.LOCAL)))
+                    }
+                }
+            }
+        }
+    }
+
+    private fun configureCapabilityExchangeTypeTest(): Pair<String, Boolean>? {
+        if (TestUtils.buildIsAtLeastU()) {
+            Log.w(CallCompatTest.TAG, "Setting up v2 tests for U+ device")
+            setUpV2Test()
+        } else {
+            Log.w(CallCompatTest.TAG, "Setting up backwards compatibility tests for pre-U device")
+            setUpBackwardsCompatTest()
+        }
+
+        // Add EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED for pre-U testing
+        return if (!TestUtils.buildIsAtLeastU())
+            Pair(CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED, true)
+        else null
+    }
+
+    /**
+     * Helper to retrieve the call from MockInCallService and wait for any call detail extras
+     * to be populated, if needed.
+     */
+    private suspend fun configureCallWithSanitizedExtras(
+        waitForCallDetailExtras: Boolean,
+        extraToInclude: Pair<String, Boolean>? = null
+    ): Call {
+        val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
+        Assert.assertNotNull("The returned Call object is <NULL>", call!!)
+
+        // Enforce waiting logic to ensure that the call details extras are populated.
+        if (waitForCallDetailExtras) {
+            TestUtils.waitOnCallExtras(call)
+        }
+
+        val callDetails = call.details
+        // Clear out extras to isolate the testing scenarios.
+        call.details.extras?.clear()
+        // Add extraToInclude for testing.
+        if (extraToInclude != null) {
+            callDetails.extras?.putBoolean(extraToInclude.first, extraToInclude.second)
+        }
+        return call
+    }
+}
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ActionsResultCallback.kt b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ActionsResultCallback.kt
new file mode 100644
index 0000000..1e6c95c
--- /dev/null
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ActionsResultCallback.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 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.core.telecom.extensions
+
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import androidx.annotation.RestrictTo
+import androidx.core.telecom.CallControlResult
+import androidx.core.telecom.CallException
+import androidx.core.telecom.internal.utils.CapabilityExchangeUtils
+import androidx.core.telecom.util.ExperimentalAppActions
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.withTimeout
+
+@ExperimentalAppActions
+@RequiresApi(Build.VERSION_CODES.O)
+@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY)
+class ActionsResultCallback : IActionsResultCallback.Stub() {
+    internal lateinit var result: CallControlResult
+    internal var errorMessage = "No error occurred"
+
+    internal val waitForActionResultLatch = CountDownLatch(1)
+
+    companion object {
+        private val TAG = ActionsResultCallback::class.simpleName
+    }
+
+    suspend fun waitForResponse(): CallControlResult {
+        try {
+            withTimeout(CapabilityExchangeUtils.ACTION_RESULT_RESPONSE_TIMEOUT) {
+                // Wait for VOIP app to return the result
+                if (waitForActionResultLatch.await(
+                        CapabilityExchangeUtils.ACTION_RESULT_RESPONSE_TIMEOUT,
+                        TimeUnit.MILLISECONDS)) {
+                    Log.i(TAG, "waitForResponse: VoIP app returned a result")
+                }
+            }
+        } catch (e: TimeoutCancellationException) {
+            Log.i(TAG, "waitForResponse: timeout reached")
+            result = CallControlResult.Error(CallException.ERROR_OPERATION_TIMED_OUT)
+        }
+        return result
+    }
+
+    override fun onFailure(errorCode: Int, msg: String?) {
+        result = CallControlResult.Error(errorCode)
+        if (msg != null) {
+            errorMessage = msg
+            Log.i(TAG, "onFailure: $errorMessage")
+        }
+
+        // Todo: define some sort of retry logic that passes the errorCode back to the ICS app in
+        //  order to allow them to determine how to handle the failure.
+
+        waitForActionResultLatch.countDown()
+    }
+
+    override fun onSuccess() {
+        result = CallControlResult.Success()
+        waitForActionResultLatch.countDown()
+    }
+}
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CapabilityExchange.kt b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CapabilityExchange.kt
index 33a79841..59e663f 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CapabilityExchange.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/CapabilityExchange.kt
@@ -26,7 +26,7 @@
     internal lateinit var capabilityExchangeListener: ICapabilityExchangeListener
     internal lateinit var voipCapabilities: MutableList<Capability>
 
-    internal val beingExchangeLatch = CountDownLatch(1)
+    internal val beginExchangeLatch = CountDownLatch(1)
 
     override fun beginExchange(
         capabilities: MutableList<Capability>?,
@@ -36,6 +36,6 @@
             voipCapabilities = capabilities
         }
         l?.let { capabilityExchangeListener = l }
-        beingExchangeLatch.countDown()
+        beginExchangeLatch.countDown()
     }
 }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantClientActionsImpl.kt b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantClientActionsImpl.kt
new file mode 100644
index 0000000..4d0e6f5
--- /dev/null
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantClientActionsImpl.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2023 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.core.telecom.extensions
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.core.telecom.CallControlResult
+import androidx.core.telecom.util.ExperimentalAppActions
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+@ExperimentalAppActions
+@RequiresApi(Build.VERSION_CODES.O)
+internal class ParticipantClientActionsImpl(
+    internal val mScope: CoroutineScope,
+    internal var mNegotiatedActions: Set<Int>,
+    internal var mOnInitializationComplete: (ParticipantClientActions) -> Unit
+) : ParticipantClientActions, IParticipantStateListener.Stub() {
+    private val mParticipantsStateFlow: MutableStateFlow<Set<Participant>> =
+        MutableStateFlow(emptySet())
+    private val mRaisedHandsStateFlow: MutableStateFlow<Set<Int>> =
+        MutableStateFlow(emptySet())
+    private val mActiveParticipantStateFlow: MutableStateFlow<Int> =
+        MutableStateFlow(-1)
+
+    internal var mIsParticipantExtensionSupported: Boolean = true
+    internal var mIsInitializationComplete = false
+    private lateinit var mActions: IParticipantActions
+
+    companion object {
+        private val TAG = ParticipantClientActionsImpl::class.simpleName
+    }
+
+    override val negotiatedActions: Set<Int>
+        get() = mNegotiatedActions
+
+    override val isParticipantExtensionSupported: Boolean
+        get() = mIsParticipantExtensionSupported
+
+    override val participantsStateFlow: StateFlow<Set<Participant>>
+        get() = mParticipantsStateFlow.asStateFlow()
+
+    override val raisedHandsStateFlow: StateFlow<Set<Int>>
+        get() = mRaisedHandsStateFlow.asStateFlow()
+
+    override val activeParticipantStateFlow: StateFlow<Int>
+        get() = mActiveParticipantStateFlow.asStateFlow()
+
+    override suspend fun toggleHandRaised(isHandRaised: Boolean): CallControlResult {
+        val resultCallback = ActionsResultCallback()
+        mActions.toggleHandRaised(resultCallback)
+
+        return mScope.async {
+            resultCallback.waitForResponse()
+        }.await()
+    }
+
+    override suspend fun kickParticipant(participantId: Int): CallControlResult {
+        val resultCallback = ActionsResultCallback()
+        mActions.kickParticipant(participantId, resultCallback)
+
+        return mScope.async {
+            resultCallback.waitForResponse()
+        }.await()
+    }
+
+    override fun updateParticipants(participants: Array<out Participant>?) {
+        participants ?: return
+        mParticipantsStateFlow.value = participants.toSet()
+    }
+
+    override fun updateActiveParticipant(activeParticipant: Int) {
+        mActiveParticipantStateFlow.value = activeParticipant
+    }
+
+    override fun updateRaisedHandsAction(participantsWithHandsRaised: IntArray?) {
+        participantsWithHandsRaised ?: return
+        mRaisedHandsStateFlow.value = participantsWithHandsRaised.toSet()
+    }
+
+    override fun finishSync(cb: IParticipantActions?) {
+        cb ?: return
+        mActions = cb
+        mIsInitializationComplete = true
+        mOnInitializationComplete(this)
+    }
+    // Todo: Consider defining an internal cache here to handle the case of out of order operations.
+}
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantClientExtension.kt b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantClientExtension.kt
new file mode 100644
index 0000000..47d6315
--- /dev/null
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/extensions/ParticipantClientExtension.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2023 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.core.telecom.extensions
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.core.telecom.CallControlResult
+import androidx.core.telecom.CallsManager
+import androidx.core.telecom.internal.CallCompat
+import androidx.core.telecom.util.ExperimentalAppActions
+import kotlinx.coroutines.flow.StateFlow
+
+// Adds extensions onto CallCompat to include participants support
+@RequiresApi(Build.VERSION_CODES.O)
+@ExperimentalAppActions
+internal object ParticipantClientExtension {
+    internal fun createCapability(actions: Set<Int>): Capability {
+        // Create the capability based on the user provided set of actions:
+        // Todo: preprocess the actions for potential user inputted errors. This can be done by
+        //  leveraging CapabilityExchangeUtils#preprocessSupportedActions
+        val participantCapability = Capability()
+        participantCapability.featureId = CallsManager.PARTICIPANT
+        participantCapability.supportedActions = actions.toIntArray()
+
+        return participantCapability
+    }
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+@ExperimentalAppActions
+internal fun CallCompat.getParticipantActions(): Result<ParticipantClientActions> {
+    return getParticipantClientActions()
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+@ExperimentalAppActions
+internal fun CallCompat.addParticipantsSupport(
+    supportedActions: Set<Int>,
+    onInitializationComplete: (ParticipantClientActions) -> Unit
+) {
+    addCapability(ParticipantClientExtension.createCapability(supportedActions))
+    // pass onInitializationComplete through to be called once everything is fully setup:
+    addExtension(onInitializationComplete)
+}
+
+// Allows the InCallService implementer to inspect state and perform requests to update state
+internal interface ParticipantClientActions {
+    val negotiatedActions: Set<Int>
+    val isParticipantExtensionSupported: Boolean
+
+    // incoming information from the voip app:
+    val participantsStateFlow: StateFlow<Set<Participant>>
+    val raisedHandsStateFlow: StateFlow<Set<Int>>
+    val activeParticipantStateFlow: StateFlow<Int>
+
+    // outgoing information to the voip app:
+    suspend fun toggleHandRaised(isHandRaised: Boolean): CallControlResult
+    suspend fun kickParticipant(participantId: Int): CallControlResult
+}
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallCompat.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallCompat.kt
index 813db71..c9ed978 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallCompat.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallCompat.kt
@@ -16,174 +16,84 @@
 
 package androidx.core.telecom.internal
 
-import android.Manifest
-import android.content.Context
-import android.content.pm.PackageManager
 import android.os.Build
 import android.os.Bundle
 import android.telecom.Call
-import android.telecom.InCallService
-import android.telecom.PhoneAccount
-import android.telecom.TelecomManager
 import android.util.Log
-import androidx.annotation.IntDef
 import androidx.annotation.RequiresApi
 import androidx.annotation.VisibleForTesting
-import androidx.core.content.ContextCompat
 import androidx.core.telecom.CallsManager
 import androidx.core.telecom.extensions.Capability
 import androidx.core.telecom.extensions.CapabilityExchange
+import androidx.core.telecom.extensions.ParticipantClientActions
+import androidx.core.telecom.extensions.ParticipantClientActionsImpl
 import androidx.core.telecom.internal.utils.CapabilityExchangeUtils
 import androidx.core.telecom.util.ExperimentalAppActions
+import java.util.concurrent.CancellationException
 import java.util.concurrent.TimeUnit
+import kotlin.math.min
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.TimeoutCancellationException
 import kotlinx.coroutines.async
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withTimeout
 
 @ExperimentalAppActions
 @RequiresApi(Build.VERSION_CODES.O)
 internal class CallCompat(
-    call: Call,
-    context: Context,
-    scope: CoroutineScope,
-    service: InCallServiceCompat
+    private val call: Call,
+    val scope: CoroutineScope,
 ) {
-    private val mCall: Call = call
-    private val mCallCompat: CallCompat = this
-    private val mSupportedCapabilities = mutableListOf(Capability())
-    private var mContext: Context = context
-    private var mScope: CoroutineScope = scope
-    private var mServiceCompat: InCallServiceCompat = service
+    internal val icsCapabilities = mutableListOf<Capability>()
+
     @VisibleForTesting
-    internal var mCapExchangeSuccess = false
-    @VisibleForTesting
-    internal var mExtensionLevelSupport = -1
+    internal var capExchangeSetupComplete = false
+
+    internal lateinit var onParticipantInitializationComplete: (ParticipantClientActions) -> Unit
+    internal lateinit var participantStateListener: ParticipantClientActionsImpl
 
     companion object {
         /**
-         * Constants used to denote the extension level supported by the VOIP app.
-         */
-        @Retention(AnnotationRetention.SOURCE)
-        @IntDef(NONE, EXTRAS, CAPABILITY_EXCHANGE, UNKNOWN)
-        internal annotation class CapabilityExchangeType
-
-        internal const val NONE = 0
-        internal const val EXTRAS = 1
-        internal const val CAPABILITY_EXCHANGE = 2
-        internal const val UNKNOWN = 3
-
-        /**
          * Current capability exchange version
          */
         internal const val CAPABILITY_EXCHANGE_VERSION = 1
 
         private val TAG = CallCompat::class.simpleName
-    }
 
-    private fun onCallCreated(callCompat: CallCompat) {
-        Log.d(TAG, "onCallCreated for callCompat = $callCompat")
-        mServiceCompat.mCallCompats.add(callCompat)
-    }
-
-    /**
-     * Internal logic that leverages [resolveCallExtensionsType] to determine whether capability
-     * exchange is supported or not when [InCallService.onCallAdded] is invoked. If
-     * [resolveCallExtensionsType] returns [CAPABILITY_EXCHANGE] then this method leverages
-     * [CallCompat.initiateICSCapabilityExchange] to initiate the process of capability exchange.
-     */
-    internal fun processCallAdded() {
-        Log.d(TAG, "processCallAdded for call = $mCall")
-        mExtensionLevelSupport = resolveCallExtensionsType(mCall)
-        Log.d(TAG, "onCallAdded: resolveCallExtensionsType returned " +
-            "$mExtensionLevelSupport for call = $mCall")
-        try {
-            when (mExtensionLevelSupport) {
-                // Case where the VOIP app is using V1.5 CS and ICS is using an extensions library:
-                EXTRAS -> {
-                    throw UnsupportedOperationException("resolveCallExtensionsType returned " +
-                        "EXTRAS; This is not yet supported.")
-                }
-
-                // Case when the VOIP app and InCallService both support capability exchange:
-                CAPABILITY_EXCHANGE -> {
-                    mScope.launch {
-                        initialize()
-                        withContext(Dispatchers.Main) {
-                            onCallCreated(mCallCompat)
-                        }
-                    }
-                }
-            }
-        } catch (e: UnsupportedOperationException) {
-            Log.e(TAG, "$e")
+        fun toCallCompat(call: Call, scope: CoroutineScope, init: CallCompat.() -> Unit):
+            CallCompat {
+            Log.i(TAG, "toCallCompat; call = $call")
+            val callCompat = CallCompat(call, scope)
+            callCompat.init()
+            return callCompat
         }
     }
 
-    /**
-     * Internal helper used by the [CallCompat] to help resolve the call extension type. This
-     * is invoked before capability exchange between the [InCallService] and VOIP app starts to
-     * ensure the necessary features are enabled to support it.
-     *
-     * If the call is placed using the V1.5 ConnectionService + Extensions Library (Auto Case), the
-     * call will have the [CallsManager.EXTRA_VOIP_API_VERSION] defined in the extras. The call
-     * extension would be resolved as [EXTRAS].
-     *
-     * If the call is using the v2 APIs and the phone account associated with the call supports
-     * transactional ops (U+) or the call has the [CallsManager.PROPERTY_IS_TRANSACTIONAL] property
-     * defined (on V devices), then the extension type is [CAPABILITY_EXCHANGE].
-     *
-     * If the call is added via CallsManager#addCall on pre-U devices and the
-     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] is present in the call extras,
-     * the extension type also resolves to [CAPABILITY_EXCHANGE].
-     *
-     * In the case that none of the cases above apply and the phone account is found not to support
-     * transactional ops (assumes that caller has [android.Manifest.permission.READ_PHONE_NUMBERS]
-     * permission), then the extension type is [NONE].
-     *
-     * If the caller does not have the required permission to retrieve the phone account, then
-     * the extension type will be [UNKNOWN], until it can be resolved.
-     *
-     * @param call to resolve the extension type for.
-     * @return the extension type [CapabilityExchangeType] resolved for the
-     * call.
-     */
-    internal fun resolveCallExtensionsType(call: Call): Int {
-        var callDetails = call.details
-        val callExtras = callDetails?.extras ?: Bundle()
+    fun toCall(): Call {
+        return call
+    }
 
-        if (callExtras.containsKey(CallsManager.EXTRA_VOIP_API_VERSION)) {
-            return EXTRAS
-        }
-        if (callDetails?.hasProperty(CallsManager.PROPERTY_IS_TRANSACTIONAL) == true || callExtras
-                .containsKey(CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED)) {
-            return CAPABILITY_EXCHANGE
-        }
-        // Verify read phone numbers permission to see if phone account supports transactional ops.
-        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_PHONE_NUMBERS)
-            == PackageManager.PERMISSION_GRANTED) {
-            var telecomManager = mContext.getSystemService(Context.TELECOM_SERVICE)
-                as TelecomManager
-            var phoneAccount = telecomManager.getPhoneAccount(callDetails?.accountHandle)
-            if (phoneAccount?.hasCapabilities(
-                    PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS) == true) {
-                return CAPABILITY_EXCHANGE
+    internal fun getParticipantClientActions(): Result<ParticipantClientActions> {
+        Log.i(TAG, "getParticipantClientActions")
+        return if (this::participantStateListener.isInitialized) {
+            if (participantStateListener.mIsInitializationComplete) {
+                Result.success(participantStateListener)
             } else {
-                return NONE
+                Result.failure(IllegalAccessException("ParticipantClientActions not setup yet."))
             }
+        } else {
+            Result.failure(IllegalAccessException("The participantStateListener field in " +
+                "CallCompat was not initialized."))
         }
-
-        Log.i(TAG, "Unable to resolve call extension type. Returning $UNKNOWN.")
-        return UNKNOWN
     }
 
-    private suspend fun initialize() {
-        mCapExchangeSuccess = initiateICSCapabilityExchange(mCall)
-        Log.d(TAG, "initialize: initiateICSCapabilityExchange returned " +
-            "$mCapExchangeSuccess for call = $mCall")
+    internal fun addCapability(capability: Capability) {
+        Log.i(TAG, "addCapability capability = $capability")
+        // This is called by extensions to include their capabilities to the call.
+        icsCapabilities.add(capability)
+    }
+
+    internal fun addExtension(onInitializationComplete: (pca: ParticipantClientActions) -> Unit) {
+        Log.i(TAG, "addExtension")
+        >
     }
 
     /**
@@ -198,15 +108,13 @@
      * the aforementioned stages of ACK fails (i.e. timeout), the negotiation will fail.
      *
      * Note: Negotiation is only supported by InCallServices that support capability exchange
-     * ([CAPABILITY_EXCHANGE]).
+     * ([InCallServiceCompat.CAPABILITY_EXCHANGE]).
      *
-     * @param call to initiate capability exchange for.
      * @return the capability negotiation status.
      * between the ICS and VOIP app.
      */
-    internal suspend fun initiateICSCapabilityExchange(call: Call): Boolean {
-        Log.i(TAG, "initiateICSCapabilityExchange: " +
-            "Starting capability negotiation with VOIP app...")
+    internal suspend fun startCapabilityExchange() {
+        Log.i(TAG, "startCapabilityExchange: Starting capability negotiation with VOIP app...")
 
         // Initialize binder for facilitating IPC (capability exchange) between ICS and VOIP app
         // and notify VOIP app via a call event.
@@ -221,7 +129,7 @@
 
         // Launch a new coroutine from the context of the current coroutine and wait for task to
         // complete.
-        return mScope.async {
+        scope.async {
             beginCapabilityNegotiationAck(capExchange)
         }.await()
     }
@@ -230,35 +138,114 @@
      * Helper to start acknowledgement process for capability negotiation between the ICS and VOIP
      * app.
      */
-    private suspend fun beginCapabilityNegotiationAck(capExchange: CapabilityExchange): Boolean {
-        var negotiationAckStatus = false
+    private suspend fun beginCapabilityNegotiationAck(capExchange: CapabilityExchange) {
+        Log.i(TAG, "beginCapabilityNegotiationAck")
+
         try {
             withTimeout(CapabilityExchangeUtils.CAPABILITY_NEGOTIATION_COROUTINE_TIMEOUT) {
                 // Wait for VOIP app to return its supported capabilities.
-                if (capExchange.beingExchangeLatch.await(
+                if (capExchange.beginExchangeLatch.await(
                         CapabilityExchangeUtils.CAPABILITY_EXCHANGE_TIMEOUT,
                         TimeUnit.MILLISECONDS)) {
-                    // Todo: Start syncing capabilities and wait for ACKs on VOIP side. Only then
-                    //  can we say that negotiation has been successful.
+                    Log.i(TAG, "beginCapabilityNegotiationAck beginExchange returned from " +
+                        "the VOIP side.")
 
-                    // Todo: negotiationAckStatus should be set based on the results of syncing.
-                    Log.i(TAG, "initiateICSCapabilityExchange: " +
-                            "Completed capability exchange feature set up.")
-                    negotiationAckStatus = true
-                }
+                    setupSupportedCapabilities(capExchange)
 
-                // Report negotiation acknowledgement failure, if it occurred.
-                if (!negotiationAckStatus) {
-                    Log.i(
-                        TAG, "initiateICSCapabilityExchange: Unable to complete capability " +
-                        "exchange feature set up.")
+                    Log.i(TAG, "beginCapabilityNegotiationAck: " +
+                        "Completed capability exchange feature set up.")
+                    capExchangeSetupComplete = true
                 }
             }
-        } catch (e: TimeoutCancellationException) {
-            Log.i(
-                TAG, "initiateICSCapabilityExchange: Capability negotiation job timed " +
-                "out in ICS side.")
+        } catch (e: Exception) {
+            when (e) {
+                is CancellationException -> {
+                    Log.i(
+                        TAG, "beginCapabilityNegotiationAck: Capability negotiation job " +
+                            "timed out in ICS side."
+                    )
+                    completeParticipantCapExchangeUnsupported()
+                    // Todo: complete other extensions exceptionally
+                }
+                else -> {
+                    // Handle the case where the VOIP app dies:
+                    Log.i(
+                        TAG, "beginCapabilityNegotiationAck: Remote party threw exception = $e"
+                    )
+                    completeParticipantCapExchangeUnsupported()
+                    // Todo: complete other extensions exceptionally
+                }
+            }
         }
-        return negotiationAckStatus
+    }
+
+    /***********************************************************************************************
+     *                           Helpers
+     *********************************************************************************************/
+
+    internal fun setupSupportedCapabilities(capExchange: CapabilityExchange) {
+        val voipCaps: Set<Capability> = capExchange.voipCapabilities.toSet()
+        for (icsCap in icsCapabilities) {
+            // Check if the VoIP app supports this capability:
+            val voipCap: Capability? = voipCaps.find {
+                it.featureId == icsCap.featureId
+            }
+
+            // If so, then initialize the listener and send the relevant callback:
+            if (voipCap != null) {
+                val negotiatedActions = icsCap.supportedActions
+                    .intersect(voipCap.supportedActions.toSet())
+                val minExtVersion = min(icsCap.featureVersion,
+                    voipCap.featureVersion)
+
+                when (icsCap.featureId) {
+                    CallsManager.PARTICIPANT -> initializeParticipantListenerAndInformVoipApp(
+                        negotiatedActions, minExtVersion, capExchange)
+                    CallsManager.CALL_ICON -> initializeCallIconListenerAndInformVoipApp(
+                        negotiatedActions, minExtVersion, capExchange)
+                }
+            } else {
+                when (icsCap.featureId) {
+                    CallsManager.PARTICIPANT -> completeParticipantCapExchangeUnsupported()
+                    CallsManager.CALL_ICON -> completeCallIconCapExchangeUnsupported()
+                }
+            }
+        }
+    }
+
+    private fun initializeParticipantListenerAndInformVoipApp(
+        negotiatedParticipantActions: Set<Int>,
+        minVersion: Int,
+        capExchange: CapabilityExchange
+    ) {
+        participantStateListener = ParticipantClientActionsImpl(scope, negotiatedParticipantActions,
+            onParticipantInitializationComplete)
+        capExchange.capabilityExchangeListener.onCreateParticipantExtension(
+            minVersion,
+            negotiatedParticipantActions.toIntArray(),
+            participantStateListener)
+    }
+
+    private fun initializeCallIconListenerAndInformVoipApp(
+        negotiatedCallIconActions: Set<Int>,
+        minVersion: Int,
+        capExchange: CapabilityExchange
+    ) {
+        Log.i(TAG, "initializeCallIconListenerAndInformVoipApp: size of negotiatedActions" +
+            " = ${negotiatedCallIconActions.size}, version = $minVersion, " +
+            "capExchange = $capExchange")
+        // Todo: initialize ICallDetailsListener and send onCreateCallDetailsExtension.
+    }
+
+    private fun completeParticipantCapExchangeUnsupported() {
+        // complete the call cap exchange exceptionally and let Telecom take care of the cleanup:
+        participantStateListener = ParticipantClientActionsImpl(scope, emptySet()) {}
+        participantStateListener.mIsParticipantExtensionSupported = false
+        onParticipantInitializationComplete(participantStateListener)
+    }
+
+    private fun completeCallIconCapExchangeUnsupported() {
+        Log.i(TAG, "completeCallIconCapExchangeUnsupported")
+        // Todo: inform the ICS app that voip doesn't support CallDetails extension
     }
 }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/InCallServiceCompat.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/InCallServiceCompat.kt
index c351f5c..4d37c65 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/InCallServiceCompat.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/InCallServiceCompat.kt
@@ -16,16 +16,27 @@
 
 package androidx.core.telecom.internal
 
+import android.Manifest
 import android.content.Context
+import android.content.pm.PackageManager
 import android.os.Build
+import android.os.Bundle
 import android.telecom.Call
 import android.telecom.InCallService
+import android.telecom.PhoneAccount
+import android.telecom.TelecomManager
+import android.util.Log
+import androidx.annotation.IntDef
 import androidx.annotation.NonNull
 import androidx.annotation.RequiresApi
+import androidx.annotation.VisibleForTesting
+import androidx.core.content.ContextCompat
+import androidx.core.telecom.CallsManager
 import androidx.core.telecom.util.ExperimentalAppActions
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
 
 /**
  * This class defines the Jetpack ICS layer which will be leveraged as part of supporting VOIP app
@@ -37,9 +48,23 @@
     internal lateinit var mContext: Context
     private lateinit var mScope: CoroutineScope
     val mCallCompats = mutableListOf<CallCompat>()
+    @VisibleForTesting
+    var mExtensionLevelSupport = -1
 
     companion object {
         private val TAG = InCallServiceCompat::class.simpleName
+
+        /**
+         * Constants used to denote the extension level supported by the VOIP app.
+         */
+        @Retention(AnnotationRetention.SOURCE)
+        @IntDef(NONE, EXTRAS, CAPABILITY_EXCHANGE, UNKNOWN)
+        internal annotation class CapabilityExchangeType
+
+        internal const val NONE = 0
+        internal const val EXTRAS = 1
+        internal const val CAPABILITY_EXCHANGE = 2
+        internal const val UNKNOWN = 3
     }
 
     override fun onCreate() {
@@ -49,13 +74,110 @@
 
     override fun onDestroy() {
         super.onDestroy()
+        // Todo: invoke CapabilityExchangeListener#onRemoveExtensions to inform the VOIP app
         mScope.cancel()
     }
 
     @RequiresApi(Build.VERSION_CODES.O)
     override fun onCallAdded(@NonNull call: Call) {
         super.onCallAdded(call)
-        val callCompat = CallCompat(call, mContext, mScope, this)
-        callCompat.processCallAdded()
+        processCallAdded(call)
+    }
+
+    /**
+     * Internal logic that leverages [resolveCallExtensionsType] to determine whether capability
+     * exchange is supported or not when [InCallService.onCallAdded] is invoked. If
+     * [resolveCallExtensionsType] returns [CAPABILITY_EXCHANGE] then this method leverages
+     * [CallCompat.startCapabilityExchange] to initiate the process of capability exchange.
+     */
+    internal fun processCallAdded(call: Call) {
+        Log.d(TAG, "processCallAdded for call = $call")
+        // invoke onCreateCallCompat and use CallCompat below
+        mExtensionLevelSupport = resolveCallExtensionsType(call)
+        Log.d(TAG, "onCallAdded: resolveCallExtensionsType returned " +
+            "$mExtensionLevelSupport for call = $call")
+        try {
+            when (mExtensionLevelSupport) {
+                // Case where the VOIP app is using V1.5 CS and ICS is using an extensions library:
+                EXTRAS -> {
+                    throw UnsupportedOperationException("resolveCallExtensionsType returned " +
+                        "EXTRAS; This is not yet supported.")
+                }
+
+                // Case when the VOIP app and InCallService both support capability exchange:
+                CAPABILITY_EXCHANGE -> {
+                    mScope.launch {
+                        val callCompat = onCreateCallCompat(call)
+                        mCallCompats.add(callCompat)
+                        callCompat.startCapabilityExchange()
+                    }
+                }
+            }
+        } catch (e: UnsupportedOperationException) {
+            Log.e(TAG, "$e")
+        }
+    }
+
+    open fun onCreateCallCompat(call: Call): CallCompat {
+        Log.d(TAG, "onCreateCallCompat for call = $call")
+        // By default, return CallCompat with no extensions:
+        return CallCompat.toCallCompat(call, mScope) {}
+    }
+
+    /**
+     * Internal helper used by the [CallCompat] to help resolve the call extension type. This
+     * is invoked before capability exchange between the [InCallService] and VOIP app starts to
+     * ensure the necessary features are enabled to support it.
+     *
+     * If the call is placed using the V1.5 ConnectionService + Extensions Library (Auto Case), the
+     * call will have the [CallsManager.EXTRA_VOIP_API_VERSION] defined in the extras. The call
+     * extension would be resolved as [EXTRAS].
+     *
+     * If the call is using the v2 APIs and the phone account associated with the call supports
+     * transactional ops (U+) or the call has the [CallsManager.PROPERTY_IS_TRANSACTIONAL] property
+     * defined (on V devices), then the extension type is [CAPABILITY_EXCHANGE].
+     *
+     * If the call is added via CallsManager#addCall on pre-U devices and the
+     * [CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED] is present in the call extras,
+     * the extension type also resolves to [CAPABILITY_EXCHANGE].
+     *
+     * In the case that none of the cases above apply and the phone account is found not to support
+     * transactional ops (assumes that caller has [android.Manifest.permission.READ_PHONE_NUMBERS]
+     * permission), then the extension type is [NONE].
+     *
+     * If the caller does not have the required permission to retrieve the phone account, then
+     * the extension type will be [UNKNOWN], until it can be resolved.
+     *
+     * @param call to resolve the extension type for.
+     * @return the extension type [CapabilityExchangeType] resolved for the
+     * call.
+     */
+    internal fun resolveCallExtensionsType(call: Call): Int {
+        var callDetails = call.details
+        val callExtras = callDetails?.extras ?: Bundle()
+
+        if (callExtras.containsKey(CallsManager.EXTRA_VOIP_API_VERSION)) {
+            return EXTRAS
+        }
+        if (callDetails?.hasProperty(CallsManager.PROPERTY_IS_TRANSACTIONAL) == true || callExtras
+                .containsKey(CallsManager.EXTRA_VOIP_BACKWARDS_COMPATIBILITY_SUPPORTED)) {
+            return CAPABILITY_EXCHANGE
+        }
+        // Verify read phone numbers permission to see if phone account supports transactional ops.
+        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_PHONE_NUMBERS)
+            == PackageManager.PERMISSION_GRANTED) {
+            var telecomManager = mContext.getSystemService(Context.TELECOM_SERVICE)
+                as TelecomManager
+            var phoneAccount = telecomManager.getPhoneAccount(callDetails?.accountHandle)
+            if (phoneAccount?.hasCapabilities(
+                    PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS) == true) {
+                return CAPABILITY_EXCHANGE
+            } else {
+                return NONE
+            }
+        }
+
+        Log.i(TAG, "Unable to resolve call extension type. Returning $UNKNOWN.")
+        return UNKNOWN
     }
 }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/CapabilityExchangeUtils.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/CapabilityExchangeUtils.kt
index 054890f..1db54cc 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/CapabilityExchangeUtils.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/CapabilityExchangeUtils.kt
@@ -35,6 +35,7 @@
          */
         internal const val CAPABILITY_EXCHANGE_TIMEOUT = 1000L
         internal const val CAPABILITY_NEGOTIATION_COROUTINE_TIMEOUT = 3000L
+        internal const val ACTION_RESULT_RESPONSE_TIMEOUT = 1000L
 
         /**
          * Constants used to denote the types of error codes that can be returned from the provided
diff --git a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
index 7fbc420..454cfcd 100644
--- a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
@@ -144,7 +144,6 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testShortcutInfo() {
         final String shortcutId = "my-shortcut";
@@ -196,7 +195,6 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testContentTitle() {
         Notification n = new NotificationCompat.Builder(mContext)
@@ -205,7 +203,6 @@
         assertEquals("testContentTitle", NotificationCompat.getContentTitle(n));
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testContentText() {
         Notification n = new NotificationCompat.Builder(mContext)
@@ -214,7 +211,6 @@
         assertEquals("testContentText", NotificationCompat.getContentText(n));
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testContentInfo() {
         Notification n = new NotificationCompat.Builder(mContext)
@@ -223,7 +219,6 @@
         assertEquals("testContentInfo", NotificationCompat.getContentInfo(n));
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testSubText() {
         Notification n = new NotificationCompat.Builder(mContext)
@@ -232,21 +227,6 @@
         assertEquals("testSubText", NotificationCompat.getSubText(n));
     }
 
-    @SdkSuppress(maxSdkVersion = 15)
-    @Test
-    public void testActionsUnsupported() {
-        NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
-        Notification nWith = builder.addAction(0, "testAction", null).build();
-        // Version prior to API 16 do not support Actions.
-        assertEquals(0, NotificationCompat.getActionCount(nWith));
-        NotificationCompat.Action action = NotificationCompat.getAction(nWith, 0);
-        assertNull(action);
-
-        Notification nWithout = builder.clearActions().build();
-        assertEquals(0, NotificationCompat.getActionCount(nWithout));
-    }
-
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testActions() {
         NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
@@ -498,7 +478,6 @@
      * original style.
      */
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testStyle_recoveredCorrectly() throws Exception {
         for (Class<? extends Style> styleSubclass : getStyleSubclasses()) {
             final Style original;
@@ -550,7 +529,6 @@
         return styleSubclasses;
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testBuilderFromNotification_fromMinimalPlatform() {
         Notification original = new Notification.Builder(mContext).build();
@@ -558,7 +536,6 @@
         assertEquals(original.toString(), recovered.toString());
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testBuilderFromNotification_fromSimpleCompat() {
         Notification original = new NotificationCompat.Builder(mContext, "channelId")
@@ -570,7 +547,6 @@
         assertNotificationEquals(original, recovered);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testBuilderFromNotification_withSmallResIdAndLargeBitmap() {
         int smallIcon = R.drawable.ic_call_answer;
@@ -606,7 +582,6 @@
         assertThat(recovered.getLargeIcon().toString()).isEqualTo(largeIcon.toString());
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testBuilderFromNotification_fromMessagingStyledCompat() {
         Person person1 = new Person.Builder()
@@ -994,7 +969,6 @@
         assertEquals(1, result.getRemoteInputs().length);
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testNotificationWearableExtenderAction_noIcon() throws Throwable {
         NotificationCompat.Action a = new NotificationCompat.Action.Builder(0, "title", null)
@@ -1007,7 +981,6 @@
         assertNull(actualAction.getIconCompat());
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testNotificationWearableExtenderAction_drawableIcon() throws Throwable {
         NotificationCompat.Action a =
@@ -1021,7 +994,6 @@
         assertEquals(android.R.drawable.ic_delete, actualAction.getIconCompat().getResId());
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testNotificationWearableExtenderAction_setAllowGeneratedRepliesTrue()
             throws Throwable {
@@ -1034,7 +1006,6 @@
                 .getAllowGeneratedReplies());
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testNotificationWearableExtenderAction_setAllowGeneratedRepliesFalse()
             throws Throwable {
@@ -1061,19 +1032,6 @@
         assertEquals(icon.toIcon(mContext).toString(), notification.getSmallIcon().toString());
     }
 
-    @SdkSuppress(maxSdkVersion = 16)
-    @SmallTest
-    @Test
-    public void testNotificationWearableExtenderAction_noActions()
-            throws Throwable {
-        NotificationCompat.Action a = newActionBuilder()
-                .setAllowGeneratedReplies(true).build();
-        NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender()
-                .addAction(a);
-        Notification notification = newNotificationBuilder().extend(extender).build();
-        assertTrue(new NotificationCompat.WearableExtender(notification).getActions().size() == 0);
-    }
-
     @Test
     public void testNotificationActionBuilder_setDataOnlyRemoteInput() throws Throwable {
         NotificationCompat.Action a = newActionBuilder()
@@ -1599,7 +1557,6 @@
         assertEquals(100, n.ledOffMS);
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @SuppressWarnings("deprecation")
     @Test
     public void testBigPictureStyle_withNullBigLargeIcon() {
@@ -1734,7 +1691,6 @@
         assertNotNull(icon);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @SuppressWarnings("deprecation")
     @Test
     public void testBigPictureStyle_recoverStyleWithBitmap() {
@@ -1796,9 +1752,8 @@
         assertEquals(Icon.TYPE_RESOURCE, rebuiltIcon.getType());
     }
 
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
-    // minSdkVersion selected because extras are not populated before 19.
     // maxSdkVersion selected because EXTRA_PICTURE_ICON not set before 31.
     public void testBigPictureStyle_bigPictureWithBitmap_legacy() {
 
@@ -1917,7 +1872,6 @@
         assertEquals(Icon.TYPE_RESOURCE, rebuiltIcon.getType());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_nullPerson() {
         NotificationCompat.MessagingStyle messagingStyle =
@@ -1941,7 +1895,6 @@
         assertNull(result.get(0).getSender());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_message() {
         NotificationCompat.MessagingStyle messagingStyle =
@@ -1974,7 +1927,6 @@
         assertTrue(result.get(1).getPerson().isImportant());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_historicMessage() {
         NotificationCompat.MessagingStyle messagingStyle =
@@ -2017,7 +1969,6 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_isGroupConversation() {
         mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
@@ -2039,7 +1990,6 @@
         assertTrue(result.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_isGroupConversation_noConversationTitle() {
         mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
@@ -2061,7 +2011,6 @@
         assertTrue(result.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_isGroupConversation_withConversationTitle_legacy() {
         // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
@@ -2083,7 +2032,6 @@
         assertTrue(result.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_isGroupConversation_withoutConversationTitle_legacy() {
         // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
@@ -2105,7 +2053,6 @@
         assertFalse(result.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_isGroupConversation_withConversationTitle_legacyWithOverride() {
         // #setGroupConversation should always take precedence over legacy behavior, so a non-null
@@ -2129,7 +2076,6 @@
         assertFalse(result.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testMessagingStyle_isGroupConversation_withoutTitle_legacyWithOverride() {
         // #setGroupConversation should always take precedence over legacy behavior, so a null
@@ -2227,7 +2173,7 @@
         assertFalse(resultMessagingStyle.isGroupConversation());
     }
 
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 27)
+    @SdkSuppress(maxSdkVersion = 27)
     @Test
     public void testMessagingStyle_applyConversationTitleAndNotGroup_legacy() {
         NotificationCompat.MessagingStyle messagingStyle =
@@ -2687,7 +2633,7 @@
                 resultActions.get(1).getIconCompat().getResId());
     }
 
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationExtraText() {
         PendingIntent answerIntent = createIntent("answer");
@@ -2717,7 +2663,7 @@
                 extras.getCharSequence(NotificationCompat.EXTRA_TEXT));
     }
 
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationVerificationInfo() {
         PendingIntent answerIntent = createIntent("answer");
@@ -2767,7 +2713,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationPersonInfo() {
         PendingIntent answerIntent = createIntent("answer");
@@ -2799,7 +2745,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationIncoming() {
         // Create a placeholder icon for use with the person.
@@ -2878,7 +2824,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationIncomingVideo() {
         PendingIntent answerIntent = createIntent("answer");
@@ -2923,7 +2869,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationOngoing() {
         // Create a placeholder icon for use with the person.
@@ -2993,7 +2939,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 30)
+    @SdkSuppress(maxSdkVersion = 30)
     @Test
     public void testCallStyle_callStyleLegacyNotificationScreening() {
         // Create a placeholder icon for use with the person.
@@ -3254,7 +3200,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void getContentTitle() {
         Notification notification = new NotificationCompat.Builder(mContext, "test channel")
                 .setContentTitle("example title")
diff --git a/core/core/src/androidTest/java/androidx/core/app/RemoteInputTest.java b/core/core/src/androidTest/java/androidx/core/app/RemoteInputTest.java
index 2dc8cae..7e69b31 100644
--- a/core/core/src/androidTest/java/androidx/core/app/RemoteInputTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/RemoteInputTest.java
@@ -185,7 +185,6 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataResultsFromIntent() throws Throwable {
         Uri uri = Uri.parse("Some Uri");
@@ -198,7 +197,6 @@
         verifyIntentHasDataResults(intent, uri);
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testRemoteInputBuilder_addAndGetTextResultsFromIntent() throws Throwable {
         CharSequence charSequence = "value doesn't matter";
@@ -213,7 +211,6 @@
         verifyIntentHasTextResults(intent, charSequence);
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataAndTextResultsFromIntentDataFirst()
             throws Throwable {
@@ -230,7 +227,6 @@
         verifyIntentHasDataResults(intent, uri);
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void testRemoteInputBuilder_addAndGetDataAndTextResultsFromIntentTextFirst()
             throws Throwable {
@@ -254,7 +250,6 @@
         assertEquals(RemoteInput.SOURCE_FREE_FORM_INPUT, RemoteInput.getResultsSource(intent));
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testGetResultsSource_addDataAndTextResults() {
         CharSequence charSequence = "value doesn't matter";
@@ -268,7 +263,6 @@
         assertEquals(RemoteInput.SOURCE_FREE_FORM_INPUT, RemoteInput.getResultsSource(intent));
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testGetResultsSource_setSource() {
         Intent intent = new Intent();
@@ -278,7 +272,6 @@
         assertEquals(RemoteInput.SOURCE_CHOICE, RemoteInput.getResultsSource(intent));
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testGetResultsSource_setSourceAndAddDataAndTextResults() {
         CharSequence charSequence = "value doesn't matter";
diff --git a/core/core/src/androidTest/java/androidx/core/app/ShareCompatTest.java b/core/core/src/androidTest/java/androidx/core/app/ShareCompatTest.java
index 90f0788..91e96b5 100644
--- a/core/core/src/androidTest/java/androidx/core/app/ShareCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/ShareCompatTest.java
@@ -31,7 +31,6 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.rule.ActivityTestRule;
 
 import org.junit.Rule;
@@ -109,7 +108,6 @@
 
     @SuppressWarnings("deprecation")
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void testBuilderSingleStreamUri() {
         Activity activity = mActivityTestRule.getActivity();
         Uri uri = Uri.parse("content://fake/file");
@@ -123,7 +121,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void testBuilderMultipleStreamUris() {
         Activity activity = mActivityTestRule.getActivity();
         Uri uri1 = Uri.parse("content://fake/file1");
diff --git a/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java
index 8fefd80..9e4739d 100644
--- a/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java
@@ -201,32 +201,50 @@
                 ContextCompat.getSystemServiceName(mContext, ActivityManager.class));
         assertEquals(ALARM_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, AlarmManager.class));
+        assertEquals(APP_OPS_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, AppOpsManager.class));
         assertEquals(AUDIO_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, AudioManager.class));
+        assertEquals(BLUETOOTH_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, BluetoothManager.class));
+        assertEquals(CAPTIONING_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, CaptioningManager.class));
         assertEquals(CLIPBOARD_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, ClipboardManager.class));
         assertEquals(CONNECTIVITY_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, ConnectivityManager.class));
+        assertEquals(CONSUMER_IR_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, ConsumerIrManager.class));
         assertEquals(DEVICE_POLICY_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, DevicePolicyManager.class));
+        assertEquals(DISPLAY_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, DisplayManager.class));
         assertEquals(DOWNLOAD_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, DownloadManager.class));
         assertEquals(DROPBOX_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, DropBoxManager.class));
         assertEquals(INPUT_METHOD_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, InputMethodManager.class));
+        assertEquals(INPUT_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, InputManager.class));
         assertEquals(KEYGUARD_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, KeyguardManager.class));
         assertEquals(LAYOUT_INFLATER_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, LayoutInflater.class));
         assertEquals(LOCATION_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, LocationManager.class));
+        assertEquals(MEDIA_ROUTER_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, MediaRouter.class));
         assertEquals(NFC_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, NfcManager.class));
         assertEquals(NOTIFICATION_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, NotificationManager.class));
+        assertEquals(NSD_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, NsdManager.class));
         assertEquals(POWER_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, PowerManager.class));
+        assertEquals(PRINT_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, PrintManager.class));
         assertEquals(SEARCH_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, SearchManager.class));
         assertEquals(SENSOR_SERVICE,
@@ -241,6 +259,8 @@
                 ContextCompat.getSystemServiceName(mContext, UiModeManager.class));
         assertEquals(USB_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, UsbManager.class));
+        assertEquals(USER_SERVICE,
+                ContextCompat.getSystemServiceName(mContext, UserManager.class));
         assertEquals(VIBRATOR_SERVICE,
                 ContextCompat.getSystemServiceName(mContext, Vibrator.class));
         assertEquals(WALLPAPER_SERVICE,
@@ -254,46 +274,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16)
-    public void getSystemServiceNameApi16() {
-        assertEquals(INPUT_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, InputManager.class));
-        assertEquals(MEDIA_ROUTER_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, MediaRouter.class));
-        assertEquals(NSD_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, NsdManager.class));
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 17)
-    public void getSystemServiceNameApi17() {
-        assertEquals(DISPLAY_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, DisplayManager.class));
-        assertEquals(USER_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, UserManager.class));
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 18)
-    public void getSystemServiceNameApi18() {
-        assertEquals(BLUETOOTH_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, BluetoothManager.class));
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = 19)
-    public void getSystemServiceNameApi19() {
-        assertEquals(APP_OPS_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, AppOpsManager.class));
-        assertEquals(CAPTIONING_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, CaptioningManager.class));
-        assertEquals(CONSUMER_IR_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, ConsumerIrManager.class));
-        assertEquals(PRINT_SERVICE,
-                ContextCompat.getSystemServiceName(mContext, PrintManager.class));
-    }
-
-    @Test
     @SdkSuppress(minSdkVersion = 21)
     public void getSystemServiceNameApi21() {
         assertEquals(APPWIDGET_SERVICE,
@@ -631,7 +611,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 17)
     public void testGetDisplayFromDisplayContext() {
         final DisplayManagerCompat displayManagerCompat = DisplayManagerCompat
                 .getInstance(mContext);
@@ -673,7 +652,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 17, maxSdkVersion = 32)
+    @SdkSuppress(maxSdkVersion = 32)
     public void testGetContextForLanguage17() {
         setAppLocales(mContext, LocaleListCompat.create(Locale.JAPAN).toLanguageTags());
 
diff --git a/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java
index 4a053a7..68ff5d3 100644
--- a/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java
@@ -18,8 +18,6 @@
 
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
-import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
 import static android.os.Build.VERSION_CODES.LOLLIPOP;
 import static android.os.Build.VERSION_CODES.M;
 import static android.os.Build.VERSION_CODES.Q;
@@ -81,20 +79,6 @@
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = ICE_CREAM_SANDWICH)
-    public void makeMainSelectorActivity_preApi14() {
-        String selectorAction = Intent.ACTION_MAIN;
-        String selectorCategory = Intent.CATEGORY_APP_BROWSER;
-
-        Intent activityIntent = IntentCompat.makeMainSelectorActivity(selectorAction,
-                selectorCategory);
-
-        assertThat(activityIntent.getAction()).isEqualTo(selectorAction);
-        assertThat(activityIntent.getCategories()).containsExactly(selectorCategory);
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = ICE_CREAM_SANDWICH_MR1)
     public void makeMainSelectorActivity() {
         String selectorAction = Intent.ACTION_MAIN;
         String selectorCategory = Intent.CATEGORY_APP_BROWSER;
diff --git a/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutXmlParserTest.java b/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutXmlParserTest.java
index 853f89e..62d71b3 100644
--- a/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutXmlParserTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutXmlParserTest.java
@@ -24,7 +24,6 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
-import androidx.test.filters.SdkSuppress;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,7 +90,6 @@
             + "</shortcuts>\n";
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testParseShortcutIds() throws XmlPullParserException, IOException {
         final XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new ByteArrayInputStream(SHORTCUTS_XML.getBytes(StandardCharsets.UTF_8)),
diff --git a/core/core/src/androidTest/java/androidx/core/graphics/TypefaceCompatTest.java b/core/core/src/androidTest/java/androidx/core/graphics/TypefaceCompatTest.java
index 3d49310..c557eaf 100644
--- a/core/core/src/androidTest/java/androidx/core/graphics/TypefaceCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/graphics/TypefaceCompatTest.java
@@ -45,7 +45,6 @@
 import androidx.core.provider.FontsContractCompat;
 import androidx.core.provider.MockFontProvider;
 import androidx.core.test.R;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.testutils.WeightStyleFont;
@@ -537,7 +536,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 18) // API 14-20 backport fails on 17
     public void testTypeFaceCompatCreateWithExactStyle_upright() {
         doTypefaceCreate(false);
     }
@@ -570,20 +568,11 @@
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = 16) // API 14-20 backport fails on 17
-    public void testTypeFaceCompatCreateWithExactStyle_upright_api14_to_16() {
-        doTypefaceCreate(false);
-    }
-
-
-    @Test
-    @SdkSuppress(minSdkVersion = 18) // API 14-20 backport is too flakey for CI
     public void testTypeFaceCompatCreateWithExactStyle_italic() {
         doTypefaceCreate(true);
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = 16) // API 14-20 backport is too flakey for CI
     public void testTypeFaceCompatCreateWithExactStyle_italic_api14_to_16() {
         doTypefaceCreate(true);
     }
diff --git a/core/core/src/androidTest/java/androidx/core/location/LocationRequestCompatTestApi19.java b/core/core/src/androidTest/java/androidx/core/location/LocationRequestCompatTestApi19.java
index d57c261..7ca9524 100644
--- a/core/core/src/androidTest/java/androidx/core/location/LocationRequestCompatTestApi19.java
+++ b/core/core/src/androidTest/java/androidx/core/location/LocationRequestCompatTestApi19.java
@@ -46,7 +46,7 @@
 @SuppressWarnings("JavaReflectionMemberAccess")
 @SmallTest
 @TargetApi(31) // Suppress NewApi since APIs are @hide at API levels 19 through 30
-@SdkSuppress(minSdkVersion = 19, maxSdkVersion = 30)
+@SdkSuppress(maxSdkVersion = 30)
 public class LocationRequestCompatTestApi19 {
     private static Method sGetProviderMethod;
     private static Method sGetIntervalMethod;
diff --git a/core/core/src/androidTest/java/androidx/core/os/HandlerCompatTest.java b/core/core/src/androidTest/java/androidx/core/os/HandlerCompatTest.java
index 42c01c2..e120ddf 100644
--- a/core/core/src/androidTest/java/androidx/core/os/HandlerCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/os/HandlerCompatTest.java
@@ -28,7 +28,6 @@
 import android.os.Message;
 
 import androidx.test.filters.MediumTest;
-import androidx.test.filters.SdkSuppress;
 
 import org.junit.After;
 import org.junit.Before;
@@ -117,7 +116,6 @@
         assertTrue(latch.await(1, SECONDS));
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void createAsyncWhenAsyncAvailable() throws InterruptedException {
         Handler handler = HandlerCompat.createAsync(mThread.getLooper());
@@ -155,7 +153,6 @@
         assertTrue(latch.await(1, SECONDS));
     }
 
-    @SdkSuppress(minSdkVersion = 17)
     @Test
     public void createAsyncWithCallbackWhenAsyncAvailable() throws InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
@@ -174,7 +171,6 @@
         assertTrue(isAsync.get());
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void testHasCallbacks() {
         Runnable r = new Runnable() {
diff --git a/core/core/src/androidTest/java/androidx/core/os/MessageCompatTest.java b/core/core/src/androidTest/java/androidx/core/os/MessageCompatTest.java
index 8d1316b..5d5d014 100644
--- a/core/core/src/androidTest/java/androidx/core/os/MessageCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/os/MessageCompatTest.java
@@ -21,7 +21,6 @@
 
 import android.os.Message;
 
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
@@ -29,7 +28,6 @@
 @SmallTest
 public final class MessageCompatTest {
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void async() {
         Message message = Message.obtain();
         assertFalse(MessageCompat.isAsynchronous(message));
@@ -37,13 +35,4 @@
         assertTrue(MessageCompat.isAsynchronous(message));
         message.recycle();
     }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = 15)
-    public void asyncPreApi16() {
-        Message message = Message.obtain();
-        MessageCompat.setAsynchronous(message, true);
-        assertFalse(MessageCompat.isAsynchronous(message));
-        message.recycle();
-    }
 }
diff --git a/core/core/src/androidTest/java/androidx/core/os/ProcessCompatTest.java b/core/core/src/androidTest/java/androidx/core/os/ProcessCompatTest.java
index fb94e30..744b2e1 100644
--- a/core/core/src/androidTest/java/androidx/core/os/ProcessCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/os/ProcessCompatTest.java
@@ -21,13 +21,11 @@
 
 import android.os.Process;
 
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
 @SmallTest
-@SdkSuppress(minSdkVersion = 16)
 public class ProcessCompatTest {
 
     @Test
diff --git a/core/core/src/androidTest/java/androidx/core/os/UserHandleCompatTest.java b/core/core/src/androidTest/java/androidx/core/os/UserHandleCompatTest.java
index 0e38ec4a..e8a2422 100644
--- a/core/core/src/androidTest/java/androidx/core/os/UserHandleCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/os/UserHandleCompatTest.java
@@ -20,12 +20,10 @@
 
 import android.os.Process;
 
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
-@SdkSuppress(minSdkVersion = 17)
 @SmallTest
 public class UserHandleCompatTest {
 
diff --git a/core/core/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java b/core/core/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java
index 02f9eeb..5504fff 100644
--- a/core/core/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/text/PrecomputedTextCompatTest.java
@@ -98,7 +98,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 18)
     public void testParams_GetDefaultValues2() {
         assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 new Params.Builder(PAINT).build().getTextDirection());
diff --git a/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java
index 971a915..072cfda 100644
--- a/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java
@@ -73,7 +73,6 @@
 
 @RunWith(AndroidJUnit4.class)
 @MediumTest
-@SdkSuppress(minSdkVersion = 18)
 public class AccessibilityDelegateCompatTest extends
         BaseInstrumentationTestCase<ViewCompatActivity> {
     private static final int TIMEOUT_ASYNC_PROCESSING = 5000;
@@ -116,7 +115,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testScreenReaderFocusable_propagatesToAccessibilityNodeInfo() {
         assertFalse(ViewCompat.isScreenReaderFocusable(mView));
         assertFalse(getNodeCompatForView(mView).isScreenReaderFocusable());
@@ -134,7 +132,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testAccessibilityHeading_propagatesToAccessibilityNodeInfo() {
         assertFalse(ViewCompat.isAccessibilityHeading(mView));
         assertFalse(getNodeCompatForView(mView).isHeading());
@@ -152,7 +149,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testAccessibilityPaneTitle_propagatesToAccessibilityNodeInfo() {
         assertNull(ViewCompat.getAccessibilityPaneTitle(mView));
         assertNull(getNodeCompatForView(mView).getPaneTitle());
@@ -171,7 +167,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 27)
+    @SdkSuppress(maxSdkVersion = 27)
     public void testAccessibilityPaneTitle_isntTrackedAsPaneWithoutTitle() throws Throwable {
         // This test isn't to test the propagation up, just that the event-sending behavior
         final AccessibilityDelegateCompat mockDelegate = mock(
@@ -198,7 +194,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testAccessibilityPaneTitle_isSentOnAppearance() throws Throwable {
         final Activity activity = mActivityTestRule.getActivity();
         final CharSequence title = "Sample title";
@@ -243,7 +238,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testAccessibilityPaneTitle_parentVisible_isSentOnAppearance() throws Throwable {
         final Activity activity = mActivityTestRule.getActivity();
         mActivityTestRule.runOnUiThread(() -> {
@@ -302,7 +296,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testAccessibilityPaneTitle_parentGone_isSentOnDisappearance() throws Throwable {
         final Activity activity = mActivityTestRule.getActivity();
         mActivityTestRule.runOnUiThread(() -> {
@@ -353,7 +346,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testAccessibilityPaneTitle_isSentOnDisappearance() throws Throwable {
         final CharSequence title = "Sample title";
         ViewCompat.setAccessibilityPaneTitle(mView, title);
@@ -397,7 +389,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 25)
+    @SdkSuppress(maxSdkVersion = 25)
     public void testPerformSpanAction() {
         final ClickableSpan span1 = mock(ClickableSpan.class);
         final ClickableSpan span2 = mock(ClickableSpan.class);
@@ -615,7 +607,7 @@
 
     @FlakyTest(bugId = 206644987)
     @Test
-    @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 32) // API 33 fails 100% b/233396250
+    @SdkSuppress(maxSdkVersion = 32) // API 33 fails 100% b/233396250
     public void testSetAccessibilityPaneTitle_sendsOutCorrectEvent() throws TimeoutException {
         final Activity activity = mActivityTestRule.getActivity();
         final CharSequence title = "Sample title";
@@ -652,7 +644,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 19)
     public void testSetStateDescription_propagatesToAccessibilityNodeInfo_sendsOutCorrectEvent()
             throws TimeoutException {
         final Activity activity = mActivityTestRule.getActivity();
diff --git a/core/core/src/androidTest/java/androidx/core/view/ViewConfigurationCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/ViewConfigurationCompatTest.java
index 26c3168..d194ec9 100644
--- a/core/core/src/androidTest/java/androidx/core/view/ViewConfigurationCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/ViewConfigurationCompatTest.java
@@ -61,7 +61,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledFlingThresholds_withDeviceParams_apiPre34() {
         InputDevice device = findInputDevice(SOURCE_TOUCHSCREEN);
         if (device == null) {
@@ -87,7 +87,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledFlingThresholds_realTouchScreenDevice_apiPre34() {
         InputDevice touchScreenDevice = findInputDevice(SOURCE_TOUCHSCREEN);
         if (touchScreenDevice == null) {
@@ -112,7 +112,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledFlingThresholds_realRotaryEncoderDevice_hasNoAndroidResForFling_apiPre34() {
         InputDevice rotaryEncoderDevice = findInputDevice(SOURCE_ROTARY_ENCODER);
         if (rotaryEncoderDevice == null) {
@@ -134,7 +134,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledMinFlingVelocity_realRotaryEncoderDevice_hasAndroidResForFling_apiPre34() {
         InputDevice rotaryEncoderDevice = findInputDevice(SOURCE_ROTARY_ENCODER);
         if (rotaryEncoderDevice == null) {
@@ -153,7 +153,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledMinFlingVelocity_realRotaryEncoderDevice_hasAndroidResForNoFling_apiPre34() {
         InputDevice rotaryEncoderDevice = findInputDevice(SOURCE_ROTARY_ENCODER);
         if (rotaryEncoderDevice == null) {
@@ -172,7 +172,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledMaxFlingVelocity_hasAndroidResForFling_realRotaryEncoderDevice_apiPre34() {
         InputDevice rotaryEncoderDevice = findInputDevice(SOURCE_ROTARY_ENCODER);
         if (rotaryEncoderDevice == null) {
@@ -191,7 +191,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledMaxFlingVelocity_hasAndroidResForNoFling_realRotaryEncoderDevice_apiPre34() {
         InputDevice rotaryEncoderDevice = findInputDevice(SOURCE_ROTARY_ENCODER);
         if (rotaryEncoderDevice == null) {
@@ -210,7 +210,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 16, maxSdkVersion = 33)
+    @SdkSuppress(maxSdkVersion = 33)
     public void scaledFlingThresholds_invalidInputDeviceParameters_apiPre34() {
         assertFlingThresholds(
                 mViewConfigMock,
@@ -330,7 +330,6 @@
                         mContext, vc, inputDeviceId, axis, source));
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Nullable
     private InputDevice findInputDevice(int source) {
         InputManager inputManager =
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowCompatTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowCompatTest.kt
index a8bff14..1a6cf3b 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowCompatTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowCompatTest.kt
@@ -21,7 +21,6 @@
 import androidx.core.test.R
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.filters.SdkSuppress
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
 import org.junit.Assert.assertEquals
@@ -34,7 +33,6 @@
 class WindowCompatTest :
     BaseInstrumentationTestCase<WindowCompatActivity>(WindowCompatActivity::class.java) {
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     fun tests_setDecorFitsSystemWindows() {
         val view = mActivityTestRule.activity.findViewById<View>(R.id.view)!!
 
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsCompatActivityTest.kt
index d7ade2a..8193c29 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsCompatActivityTest.kt
@@ -22,7 +22,6 @@
 import android.view.View
 import android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
 import android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
-import androidx.annotation.RequiresApi
 import androidx.core.graphics.Insets
 import androidx.core.test.R
 import androidx.core.view.WindowInsetsCompat.Type
@@ -57,8 +56,6 @@
 import org.junit.runners.Parameterized
 
 @Suppress("DEPRECATION") // Testing deprecated methods
-@SdkSuppress(minSdkVersion = 16)
-@RequiresApi(16) // View.setSystemUiVisibility
 @LargeTest
 @RunWith(Parameterized::class)
 public class WindowInsetsCompatActivityTest(
diff --git a/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
index 2b54106..281bc49 100644
--- a/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompatTest.java
@@ -58,7 +58,6 @@
         accessibilityNodeInfoCompat.setCollectionItemInfo(null);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testSetCollectionItemInfoCompatBuilder_withDefaultValues() {
         AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfoCompat =
@@ -75,7 +74,6 @@
         assertThat(collectionItemInfoCompat.isHeading()).isFalse();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testSetCollectionInfoCompatBuilder_withRealValues() {
         AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfoCompat =
@@ -106,7 +104,6 @@
         assertThat(collectionItemInfoCompat.isHeading()).isTrue();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testRangeInfoCompatConstructor_always_returnsRangeInfoCompat() {
         AccessibilityNodeInfoCompat.RangeInfoCompat rangeInfoCompat =
@@ -165,7 +162,6 @@
         assertThat(nodeCompat.getTooltipText()).isEqualTo(tooltipText);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetShowingHintText() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -175,7 +171,6 @@
         assertThat(nodeCompat.isShowingHintText()).isFalse();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetScreenReaderFocusable() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -185,7 +180,6 @@
         assertThat(nodeCompat.isScreenReaderFocusable()).isFalse();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetMinDurationBetweenContentChanges() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -193,7 +187,6 @@
         assertThat(nodeCompat.getMinDurationBetweenContentChangesMillis()).isEqualTo(200L);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetRequestInitialAccessibilityFocus() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -210,7 +203,6 @@
         assertThat(nodeCompat.getContainerTitle()).isEqualTo(containerTitle);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetBoundsInWindow() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -231,7 +223,6 @@
         verify(accessibilityNodeInfo).setQueryFromAppProcessEnabled(null, true);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testisGranularScrollingSupported() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -240,7 +231,6 @@
         assertThat(nodeCompat.isGranularScrollingSupported()).isTrue();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetHeading() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -254,7 +244,6 @@
         assertThat(nodeCompat.isHeading()).isTrue();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetTextEntryKey() {
         AccessibilityNodeInfoCompat nodeCompat = obtainedWrappedNodeCompat();
@@ -264,7 +253,6 @@
         assertThat(nodeCompat.isTextEntryKey()).isFalse();
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testGetSetAccessibilityDataSensitive() {
         AccessibilityNodeInfoCompat accessibilityNodeInfoCompat = obtainedWrappedNodeCompat();
@@ -283,7 +271,6 @@
         assertThat(nodeCompat.getUniqueId()).isEqualTo(uniqueId);
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testAccessibilityActionsNotNull() {
         try {
@@ -332,7 +319,6 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @Test
     public void testAccessibilityActionToString() {
         AccessibilityActionCompat actionCompat;
@@ -450,7 +436,6 @@
                         accessibilityNodeInfoCompat.unwrap().getExtraRenderingInfo());
     }
 
-    @SdkSuppress(minSdkVersion = 19)
     @SmallTest
     @Test
     public void testSetGetTextSelectable() {
diff --git a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingA11yScrollTest.java b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingA11yScrollTest.java
index 8b80cfa..3009db1 100644
--- a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingA11yScrollTest.java
+++ b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingA11yScrollTest.java
@@ -43,7 +43,6 @@
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.jetbrains.annotations.NotNull;
@@ -113,16 +112,12 @@
         testContentView.awaitLayouts(2);
     }
 
-    // minSdkVersion = 16 because View.performAccessibilityAction wasn't available till then.
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void a11yActionScrollForward_fullyParticipatesInNestedScrolling() throws Throwable {
         a11yScroll_fullyParticipatesInNestedScrolling(true, /* startY= */ 0, TOTAL_SCROLL_OFFSET);
     }
 
-    // minSdkVersion = 16 because View.performAccessibilityAction wasn't available till then.
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void a11yActionScrollForward_halfVisibleSize_fullyParticipatesInNestedScrollingHalf()
             throws Throwable {
         mActivityTestRule.runOnUiThread(
@@ -134,17 +129,13 @@
                 TOTAL_SCROLL_OFFSET_HALF);
     }
 
-    // minSdkVersion = 16 because View.performAccessibilityAction wasn't available till then.
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void a11yActionScrollBackward_fullyParticipatesInNestedScrolling() throws Throwable {
         a11yScroll_fullyParticipatesInNestedScrolling(false, /* startY= */ 200,
                 -TOTAL_SCROLL_OFFSET);
     }
 
-    // minSdkVersion = 16 because View.performAccessibilityAction wasn't available till then.
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public void a11yActionScrollBackward_halfVisibleSize_fullyParticipatesInNestedScrollingHalf()
             throws Throwable {
         mActivityTestRule.runOnUiThread(
diff --git a/core/core/src/androidTest/java/androidx/core/widget/TextViewCompatTest.java b/core/core/src/androidTest/java/androidx/core/widget/TextViewCompatTest.java
index 0765571..5c9b46a 100644
--- a/core/core/src/androidTest/java/androidx/core/widget/TextViewCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/widget/TextViewCompatTest.java
@@ -733,7 +733,6 @@
 
     @UiThreadTest
     @Test
-    @SdkSuppress(minSdkVersion = 18)
     public void testSetGetTextMetricsParams_API18() {
         PrecomputedTextCompat.Params params = TextViewCompat.getTextMetricsParams(mTextView);
         assertNotNull(params);
diff --git a/core/core/src/androidTest/java/androidx/core/widget/TextViewOnReceiveContentListenerTest.java b/core/core/src/androidTest/java/androidx/core/widget/TextViewOnReceiveContentListenerTest.java
index 8da0f4a..3db4dd1 100644
--- a/core/core/src/androidTest/java/androidx/core/widget/TextViewOnReceiveContentListenerTest.java
+++ b/core/core/src/androidTest/java/androidx/core/widget/TextViewOnReceiveContentListenerTest.java
@@ -39,7 +39,6 @@
 import androidx.test.annotation.UiThreadTest;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.rule.ActivityTestRule;
 
 import org.junit.Before;
@@ -125,7 +124,6 @@
         assertThat(spanStart).isEqualTo(-1);
     }
 
-    @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
     @UiThreadTest
     @Test
     public void testOnReceive_html() throws Exception {
@@ -138,7 +136,6 @@
         assertTextAndCursorPosition("xyz", 2);
     }
 
-    @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
     @UiThreadTest
     @Test
     public void testOnReceive_html_convertToPlainText() throws Exception {
@@ -206,7 +203,6 @@
         assertTextAndCursorPosition("hi", 2);
     }
 
-    @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
     @UiThreadTest
     @Test
     public void testOnReceive_unsupportedMimeType_viaMenu() throws Exception {
@@ -220,7 +216,6 @@
         assertTextAndCursorPosition("xhtmlz", 5);
     }
 
-    @SdkSuppress(minSdkVersion = 16) // Passing HTML into a ClipData.Item was added in SDK 16.
     @UiThreadTest
     @Test
     public void testOnReceive_unsupportedMimeType_viaMenu_convertToPlainText() throws Exception {
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index d3a7dd4..2f783a9 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -339,9 +339,9 @@
     docs("androidx.startup:startup-runtime:1.2.0-alpha02")
     docs("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01")
     // androidx.test is not hosted in androidx\
-    docsWithoutApiSince("androidx.test:core:1.6.0-alpha01")
-    docsWithoutApiSince("androidx.test:core-ktx:1.6.0-alpha01")
-    docsWithoutApiSince("androidx.test:monitor:1.7.0-alpha01")
+    docsWithoutApiSince("androidx.test:core:1.6.0-alpha02")
+    docsWithoutApiSince("androidx.test:core-ktx:1.6.0-alpha02")
+    docsWithoutApiSince("androidx.test:monitor:1.7.0-alpha02")
     docsWithoutApiSince("androidx.test:rules:1.6.0-alpha01")
     docsWithoutApiSince("androidx.test:runner:1.6.0-alpha01")
     docsWithoutApiSince("androidx.test.espresso:espresso-accessibility:3.6.0-alpha01")
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index f706c7d..d69df04 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -91,6 +91,7 @@
     samples(project(":compose:material3:material3-adaptive:material3-adaptive-samples"))
     kmpDocs(project(":compose:material3:material3-adaptive-navigation-suite"))
     samples(project(":compose:material3:material3-adaptive-navigation-suite:material3-adaptive-navigation-suite-samples"))
+    docs(project(":compose:material3:material3-common"))
     samples(project(":compose:material3:material3:material3-samples"))
     kmpDocs(project(":compose:material3:material3-window-size-class"))
     samples(project(":compose:material3:material3-window-size-class:material3-window-size-class-samples"))
diff --git a/docs/lint_guide.md b/docs/lint_guide.md
index a08a143..cf62088 100644
--- a/docs/lint_guide.md
+++ b/docs/lint_guide.md
@@ -456,19 +456,18 @@
 
 ```kotlin
 override fun visitElement(context: XmlContext, element: Element) {
-    val lintFix = fix().replace()
+    val fix = LintFix.create()
+        .replace()
         .text(ELEMENT)
-        .with(REPLACEMENT TEXT)
+        .with(REPLACEMENT_TEXT)
         .build()
 
-    val incident = Incident(context)
-        .fix(lintFix)
-        .issue(ISSUE)
-        .location(context.getLocation(element))
-        .message("My issue message")
-        .scope(context.getNameLocation(element))
-
-    context.report(incident)
+    context.report(
+        issue = ISSUE,
+        location = context.getNameLocation(element),
+        message = "My issue message",
+        quickFixData = fix
+    )
 }
 ```
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt
index f487429..6dbb5aa 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/DialogFragmentDismissTest.kt
@@ -31,6 +31,7 @@
 import java.util.concurrent.TimeUnit
 import leakcanary.DetectLeaksAfterTestSuccess
 import leakcanary.SkipLeakDetection
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.RuleChain
@@ -113,6 +114,7 @@
 
     @SkipLeakDetection("There is a platform ViewRootImpl leak this is triggered on this test")
     @Test
+    @Ignore("b/308684873")
     fun testDialogFragmentDismiss() {
         // Due to b/157955883, we need to early return if API == 30.
         // Otherwise, this test flakes.
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
index da64cee..f63399f 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SaveRestoreBackStackTest.kt
@@ -30,6 +30,7 @@
 import com.google.common.truth.Truth.assertWithMessage
 import leakcanary.DetectLeaksAfterTestSuccess
 import org.junit.Assert.fail
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -127,6 +128,7 @@
     }
 
     @Test
+    @Ignore("b/308684873")
     fun saveBackStackAddedWithoutExecutePendingTransactions() {
        withUse(ActivityScenario.launch(FragmentTestActivity::class.java)) {
             val fm = withActivity {
@@ -324,6 +326,7 @@
 
     @Suppress("DEPRECATION")
     @Test
+    @Ignore("b/308684873")
     fun saveRetainedChildFragment() {
        withUse(ActivityScenario.launch(FragmentTestActivity::class.java)) {
             val fm = withActivity {
@@ -719,6 +722,7 @@
     }
 
     @Test
+    @Ignore("b/308684873")
     fun clearBackStackWithoutExecutePendingTransactions() {
        withUse(ActivityScenario.launch(FragmentTestActivity::class.java)) {
             val fm = withActivity {
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SpecialEffectsControllerTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SpecialEffectsControllerTest.kt
index 852fe8a..8a1f817 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/SpecialEffectsControllerTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/SpecialEffectsControllerTest.kt
@@ -284,6 +284,7 @@
 
     @MediumTest
     @Test
+    @Ignore("b/308684873")
     fun enqueueAddAndCancel() {
        withUse(ActivityScenario.launch(EmptyFragmentTestActivity::class.java)) {
             val container = withActivity { findViewById<ViewGroup>(android.R.id.content) }
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
index 3eb995c..2ac4209 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
@@ -34,6 +34,7 @@
 import leakcanary.SkipLeakDetection
 import org.junit.After
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -237,6 +238,7 @@
     }
 
     @Test
+    @Ignore("b/308684873")
     public fun detectWrongNestedHierarchyNoParent() {
         var violation: Violation? = null
         val policy = FragmentStrictMode.Policy.Builder()
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6cfc48b..913cc67 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -16,8 +16,8 @@
 androidLintMinCompose = "30.0.0"
 androidxTestRunner = "1.6.0-alpha01"
 androidxTestRules = "1.6.0-alpha01"
-androidxTestMonitor = "1.7.0-alpha01"
-androidxTestCore = "1.6.0-alpha01"
+androidxTestMonitor = "1.7.0-alpha02"
+androidxTestCore = "1.6.0-alpha02"
 androidxTestExtJunit = "1.2.0-alpha01"
 androidxTestExtTruth = "1.6.0-alpha01"
 annotationVersion = "1.7.0"
diff --git a/libraryversions.toml b/libraryversions.toml
index 7ee4ab8..6e854ff 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -15,8 +15,8 @@
 BROWSER = "1.8.0-alpha01"
 BUILDSRC_TESTS = "1.0.0-alpha01"
 CAMERA = "1.4.0-alpha03"
-CAMERA_TESTING = "1.0.0-alpha01"
 CAMERA_PIPE = "1.0.0-alpha01"
+CAMERA_TESTING = "1.0.0-alpha01"
 CARDVIEW = "1.1.0-alpha01"
 CAR_APP = "1.7.0-alpha01"
 COLLECTION = "1.4.0-beta01"
@@ -25,6 +25,7 @@
 COMPOSE_MATERIAL3 = "1.2.0-alpha11"
 COMPOSE_MATERIAL3_ADAPTIVE = "1.0.0-alpha01"
 COMPOSE_MATERIAL3_ADAPTIVE_NAVIGATION_SUITE = "1.0.0-alpha01"
+COMPOSE_MATERIAL3_COMMON = "1.0.0-alpha01"
 COMPOSE_RUNTIME_TRACING = "1.0.0-alpha05"
 CONSTRAINTLAYOUT = "2.2.0-alpha13"
 CONSTRAINTLAYOUT_COMPOSE = "1.1.0-alpha13"
@@ -45,7 +46,7 @@
 CORE_SPLASHSCREEN = "1.1.0-alpha02"
 CORE_TELECOM = "1.0.0-alpha02"
 CORE_UWB = "1.0.0-alpha08"
-CREDENTIALS = "1.2.0"
+CREDENTIALS = "1.3.0-alpha01"
 CREDENTIALS_FIDO_QUARANTINE = "1.0.0-alpha01"
 CURSORADAPTER = "1.1.0-alpha01"
 CUSTOMVIEW = "1.2.0-alpha03"
@@ -89,7 +90,7 @@
 LEANBACK_TAB = "1.1.0-beta01"
 LEGACY = "1.1.0-alpha01"
 LIBYUV = "0.1.0-dev01"
-LIFECYCLE = "2.7.0-beta01"
+LIFECYCLE = "2.7.0-rc01"
 LIFECYCLE_EXTENSIONS = "2.2.0"
 LOADER = "1.2.0-alpha01"
 MEDIA = "1.7.0-rc01"
@@ -105,7 +106,7 @@
 PRIVACYSANDBOX_ACTIVITY = "1.0.0-alpha01"
 PRIVACYSANDBOX_ADS = "1.1.0-beta02"
 PRIVACYSANDBOX_PLUGINS = "1.0.0-alpha03"
-PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha10"
+PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha11"
 PRIVACYSANDBOX_TOOLS = "1.0.0-alpha06"
 PRIVACYSANDBOX_UI = "1.0.0-alpha07"
 PROFILEINSTALLER = "1.4.0-alpha01"
diff --git a/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java b/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java
index 82ee56a..6c62100 100644
--- a/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java
+++ b/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java
@@ -38,6 +38,7 @@
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.os.Build;
+import org.junit.Ignore;
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.testapp.CollectingLifecycleOwner;
@@ -127,6 +128,7 @@
     }
 
     @Test
+    @Ignore("b/173596006")
     public void coveredWithDialog_fragment() throws Throwable {
         CollectingSupportFragment fragment = new CollectingSupportFragment();
         activityRule.runOnUiThread(() -> activityRule.getActivity().replaceFragment(fragment));
diff --git a/media2/media2-common/api/current.txt b/media2/media2-common/api/current.txt
index 7992d7b..3ba4f06 100644
--- a/media2/media2-common/api/current.txt
+++ b/media2/media2-common/api/current.txt
@@ -1,221 +1,221 @@
 // Signature format: 4.0
 package androidx.media2.common {
 
-  public class CallbackMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
-    method public androidx.media2.common.DataSourceCallback getDataSourceCallback();
+  @Deprecated public class CallbackMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public androidx.media2.common.DataSourceCallback getDataSourceCallback();
   }
 
-  public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
-    ctor public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
-    method public androidx.media2.common.CallbackMediaItem build();
-    method public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
+  @Deprecated public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+    ctor @Deprecated public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
+    method @Deprecated public androidx.media2.common.CallbackMediaItem build();
+    method @Deprecated public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
   }
 
-  public abstract class DataSourceCallback implements java.io.Closeable {
-    ctor public DataSourceCallback();
-    method public abstract long getSize() throws java.io.IOException;
-    method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
+  @Deprecated public abstract class DataSourceCallback implements java.io.Closeable {
+    ctor @Deprecated public DataSourceCallback();
+    method @Deprecated public abstract long getSize() throws java.io.IOException;
+    method @Deprecated public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
-  public class FileMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
-    method public long getFileDescriptorLength();
-    method public long getFileDescriptorOffset();
-    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
-    field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+  @Deprecated public class FileMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public long getFileDescriptorLength();
+    method @Deprecated public long getFileDescriptorOffset();
+    method @Deprecated public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+    field @Deprecated public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
   }
 
-  public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
-    ctor public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
-    method public androidx.media2.common.FileMediaItem build();
-    method public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
-    method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
-    method public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
+  @Deprecated public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+    ctor @Deprecated public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
+    method @Deprecated public androidx.media2.common.FileMediaItem build();
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
   }
 
-  public class MediaItem implements androidx.versionedparcelable.VersionedParcelable {
-    method public long getEndPosition();
-    method public androidx.media2.common.MediaMetadata? getMetadata();
-    method public long getStartPosition();
-    method public void setMetadata(androidx.media2.common.MediaMetadata?);
-    field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+  @Deprecated public class MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public long getEndPosition();
+    method @Deprecated public androidx.media2.common.MediaMetadata? getMetadata();
+    method @Deprecated public long getStartPosition();
+    method @Deprecated public void setMetadata(androidx.media2.common.MediaMetadata?);
+    field @Deprecated public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
   }
 
-  public static class MediaItem.Builder {
-    ctor public MediaItem.Builder();
-    method public androidx.media2.common.MediaItem build();
-    method public androidx.media2.common.MediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.MediaItem.Builder setStartPosition(long);
+  @Deprecated public static class MediaItem.Builder {
+    ctor @Deprecated public MediaItem.Builder();
+    method @Deprecated public androidx.media2.common.MediaItem build();
+    method @Deprecated public androidx.media2.common.MediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.MediaItem.Builder setStartPosition(long);
   }
 
-  public final class MediaMetadata implements androidx.versionedparcelable.VersionedParcelable {
-    method public boolean containsKey(String);
-    method public android.graphics.Bitmap? getBitmap(String);
-    method public android.os.Bundle? getExtras();
-    method public float getFloat(String);
-    method public long getLong(String);
-    method public String? getMediaId();
-    method public androidx.media2.common.Rating? getRating(String);
-    method public String? getString(String);
-    method public CharSequence? getText(String);
-    method public java.util.Set<java.lang.String!> keySet();
-    method public int size();
-    field public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
-    field public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
-    field public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
-    field public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
-    field public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
-    field public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
-    field public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
-    field public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
-    field public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
-    field public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
-    field public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
-    field public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
-    field public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
-    field public static final String METADATA_KEY_ART = "android.media.metadata.ART";
-    field public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
-    field public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
-    field public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
-    field public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
-    field public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
-    field public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
-    field public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
-    field public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
-    field public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
-    field public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
-    field public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
-    field public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
-    field public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
-    field public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
-    field public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
-    field public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
-    field public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
-    field public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
-    field public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
-    field public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
-    field public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
-    field public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
-    field public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
-    field public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
-    field public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
-    field public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
-    field public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
-    field public static final long STATUS_DOWNLOADED = 2L; // 0x2L
-    field public static final long STATUS_DOWNLOADING = 1L; // 0x1L
-    field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
+  @Deprecated public final class MediaMetadata implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public boolean containsKey(String);
+    method @Deprecated public android.graphics.Bitmap? getBitmap(String);
+    method @Deprecated public android.os.Bundle? getExtras();
+    method @Deprecated public float getFloat(String);
+    method @Deprecated public long getLong(String);
+    method @Deprecated public String? getMediaId();
+    method @Deprecated public androidx.media2.common.Rating? getRating(String);
+    method @Deprecated public String? getString(String);
+    method @Deprecated public CharSequence? getText(String);
+    method @Deprecated public java.util.Set<java.lang.String!> keySet();
+    method @Deprecated public int size();
+    field @Deprecated public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
+    field @Deprecated public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
+    field @Deprecated public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
+    field @Deprecated public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
+    field @Deprecated public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
+    field @Deprecated public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
+    field @Deprecated public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
+    field @Deprecated public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
+    field @Deprecated public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
+    field @Deprecated public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
+    field @Deprecated public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
+    field @Deprecated public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+    field @Deprecated public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
+    field @Deprecated public static final String METADATA_KEY_ART = "android.media.metadata.ART";
+    field @Deprecated public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
+    field @Deprecated public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
+    field @Deprecated public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+    field @Deprecated public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
+    field @Deprecated public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+    field @Deprecated public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
+    field @Deprecated public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
+    field @Deprecated public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
+    field @Deprecated public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
+    field @Deprecated public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
+    field @Deprecated public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
+    field @Deprecated public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+    field @Deprecated public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+    field @Deprecated public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
+    field @Deprecated public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
+    field @Deprecated public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
+    field @Deprecated public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
+    field @Deprecated public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
+    field @Deprecated public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+    field @Deprecated public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
+    field @Deprecated public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
+    field @Deprecated public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
+    field @Deprecated public static final long STATUS_DOWNLOADED = 2L; // 0x2L
+    field @Deprecated public static final long STATUS_DOWNLOADING = 1L; // 0x1L
+    field @Deprecated public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
   }
 
-  public static final class MediaMetadata.Builder {
-    ctor public MediaMetadata.Builder();
-    ctor public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
-    method public androidx.media2.common.MediaMetadata build();
-    method public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
-    method public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
-    method public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
-    method public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
-    method public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
-    method public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
-    method public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
+  @Deprecated public static final class MediaMetadata.Builder {
+    ctor @Deprecated public MediaMetadata.Builder();
+    ctor @Deprecated public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
+    method @Deprecated public androidx.media2.common.MediaMetadata build();
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
   }
 
-  public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
-    method public boolean isRated();
+  @Deprecated public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public boolean isRated();
   }
 
-  public abstract class SessionPlayer implements java.io.Closeable {
-    ctor public SessionPlayer();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
-    method @CallSuper public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
-    method public abstract long getBufferedPosition();
-    method public abstract int getBufferingState();
-    method protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
-    method public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
-    method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
-    method public abstract long getCurrentPosition();
-    method public abstract long getDuration();
-    method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
-    method public abstract float getPlaybackSpeed();
-    method public abstract int getPlayerState();
-    method public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
-    method public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
-    method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
-    method public abstract int getRepeatMode();
-    method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
-    method public abstract int getShuffleMode();
-    method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
-    method public androidx.media2.common.VideoSize getVideoSize();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
-    method public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
-    method public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
-    field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
-    field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
-    field public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
-    field public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
-    field public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
-    field public static final int PLAYER_STATE_ERROR = 3; // 0x3
-    field public static final int PLAYER_STATE_IDLE = 0; // 0x0
-    field public static final int PLAYER_STATE_PAUSED = 1; // 0x1
-    field public static final int PLAYER_STATE_PLAYING = 2; // 0x2
-    field public static final int REPEAT_MODE_ALL = 2; // 0x2
-    field public static final int REPEAT_MODE_GROUP = 3; // 0x3
-    field public static final int REPEAT_MODE_NONE = 0; // 0x0
-    field public static final int REPEAT_MODE_ONE = 1; // 0x1
-    field public static final int SHUFFLE_MODE_ALL = 1; // 0x1
-    field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
-    field public static final int SHUFFLE_MODE_NONE = 0; // 0x0
-    field public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
+  @Deprecated public abstract class SessionPlayer implements java.io.Closeable {
+    ctor @Deprecated public SessionPlayer();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated @CallSuper public void close();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
+    method @Deprecated public abstract long getBufferedPosition();
+    method @Deprecated public abstract int getBufferingState();
+    method @Deprecated protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
+    method @Deprecated public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
+    method @Deprecated @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
+    method @Deprecated public abstract long getCurrentPosition();
+    method @Deprecated public abstract long getDuration();
+    method @Deprecated @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
+    method @Deprecated public abstract float getPlaybackSpeed();
+    method @Deprecated public abstract int getPlayerState();
+    method @Deprecated public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+    method @Deprecated public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+    method @Deprecated @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
+    method @Deprecated public abstract int getRepeatMode();
+    method @Deprecated public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+    method @Deprecated public abstract int getShuffleMode();
+    method @Deprecated public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+    method @Deprecated public androidx.media2.common.VideoSize getVideoSize();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+    method @Deprecated public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+    method @Deprecated public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+    field @Deprecated public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
+    field @Deprecated public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
+    field @Deprecated public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
+    field @Deprecated public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
+    field @Deprecated public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
+    field @Deprecated public static final int PLAYER_STATE_ERROR = 3; // 0x3
+    field @Deprecated public static final int PLAYER_STATE_IDLE = 0; // 0x0
+    field @Deprecated public static final int PLAYER_STATE_PAUSED = 1; // 0x1
+    field @Deprecated public static final int PLAYER_STATE_PLAYING = 2; // 0x2
+    field @Deprecated public static final int REPEAT_MODE_ALL = 2; // 0x2
+    field @Deprecated public static final int REPEAT_MODE_GROUP = 3; // 0x3
+    field @Deprecated public static final int REPEAT_MODE_NONE = 0; // 0x0
+    field @Deprecated public static final int REPEAT_MODE_ONE = 1; // 0x1
+    field @Deprecated public static final int SHUFFLE_MODE_ALL = 1; // 0x1
+    field @Deprecated public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
+    field @Deprecated public static final int SHUFFLE_MODE_NONE = 0; // 0x0
+    field @Deprecated public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
   }
 
-  public abstract static class SessionPlayer.PlayerCallback {
-    ctor public SessionPlayer.PlayerCallback();
-    method public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
-    method public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
-    method public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?);
-    method public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
-    method public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
-    method public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
-    method public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
-    method public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
-    method public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
-    method public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
-    method public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
-    method public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
-    method public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
-    method public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
+  @Deprecated public abstract static class SessionPlayer.PlayerCallback {
+    ctor @Deprecated public SessionPlayer.PlayerCallback();
+    method @Deprecated public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
+    method @Deprecated public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
+    method @Deprecated public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?);
+    method @Deprecated public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
+    method @Deprecated public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
+    method @Deprecated public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
+    method @Deprecated public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
+    method @Deprecated public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
+    method @Deprecated public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
+    method @Deprecated public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+    method @Deprecated public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+    method @Deprecated public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
   }
 
-  public static class SessionPlayer.PlayerResult {
-    ctor public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
-    method public long getCompletionTime();
-    method public androidx.media2.common.MediaItem? getMediaItem();
-    method public int getResultCode();
+  @Deprecated public static class SessionPlayer.PlayerResult {
+    ctor @Deprecated public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
+    method @Deprecated public long getCompletionTime();
+    method @Deprecated public androidx.media2.common.MediaItem? getMediaItem();
+    method @Deprecated public int getResultCode();
     field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
     field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
     field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
@@ -226,47 +226,47 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  public static class SessionPlayer.TrackInfo implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
-    ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
-    method public android.media.MediaFormat? getFormat();
-    method public int getId();
-    method public java.util.Locale getLanguage();
-    method public int getTrackType();
-    method public boolean isSelectable();
-    field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
-    field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
-    field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
-    field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
+  @Deprecated public static class SessionPlayer.TrackInfo implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
+    ctor @Deprecated public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
+    method @Deprecated public android.media.MediaFormat? getFormat();
+    method @Deprecated public int getId();
+    method @Deprecated public java.util.Locale getLanguage();
+    method @Deprecated public int getTrackType();
+    method @Deprecated public boolean isSelectable();
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
   }
 
-  public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SubtitleData(long, long, byte[]);
-    method public byte[] getData();
-    method public long getDurationUs();
-    method public long getStartTimeUs();
+  @Deprecated public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SubtitleData(long, long, byte[]);
+    method @Deprecated public byte[] getData();
+    method @Deprecated public long getDurationUs();
+    method @Deprecated public long getStartTimeUs();
   }
 
-  public class UriMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
-    method public android.net.Uri getUri();
-    method public java.util.List<java.net.HttpCookie!>? getUriCookies();
-    method public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
+  @Deprecated public class UriMediaItem extends androidx.media2.common.MediaItem implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public android.net.Uri getUri();
+    method @Deprecated public java.util.List<java.net.HttpCookie!>? getUriCookies();
+    method @Deprecated public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
   }
 
-  public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
-    ctor public UriMediaItem.Builder(android.net.Uri);
-    ctor public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
-    method public androidx.media2.common.UriMediaItem build();
-    method public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
+  @Deprecated public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+    ctor @Deprecated public UriMediaItem.Builder(android.net.Uri);
+    ctor @Deprecated public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
+    method @Deprecated public androidx.media2.common.UriMediaItem build();
+    method @Deprecated public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
   }
 
-  public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
-    method @IntRange(from=0) public int getHeight();
-    method @IntRange(from=0) public int getWidth();
+  @Deprecated public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @Deprecated @IntRange(from=0) public int getHeight();
+    method @Deprecated @IntRange(from=0) public int getWidth();
   }
 
 }
diff --git a/media2/media2-common/api/restricted_current.txt b/media2/media2-common/api/restricted_current.txt
index 097aa96..b3a7b21 100644
--- a/media2/media2-common/api/restricted_current.txt
+++ b/media2/media2-common/api/restricted_current.txt
@@ -1,221 +1,221 @@
 // Signature format: 4.0
 package androidx.media2.common {
 
-  public class CallbackMediaItem extends androidx.media2.common.MediaItem {
-    method public androidx.media2.common.DataSourceCallback getDataSourceCallback();
+  @Deprecated public class CallbackMediaItem extends androidx.media2.common.MediaItem {
+    method @Deprecated public androidx.media2.common.DataSourceCallback getDataSourceCallback();
   }
 
-  public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
-    ctor public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
-    method public androidx.media2.common.CallbackMediaItem build();
-    method public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
+  @Deprecated public static final class CallbackMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+    ctor @Deprecated public CallbackMediaItem.Builder(androidx.media2.common.DataSourceCallback);
+    method @Deprecated public androidx.media2.common.CallbackMediaItem build();
+    method @Deprecated public androidx.media2.common.CallbackMediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.CallbackMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.CallbackMediaItem.Builder setStartPosition(long);
   }
 
-  public abstract class DataSourceCallback implements java.io.Closeable {
-    ctor public DataSourceCallback();
-    method public abstract long getSize() throws java.io.IOException;
-    method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
+  @Deprecated public abstract class DataSourceCallback implements java.io.Closeable {
+    ctor @Deprecated public DataSourceCallback();
+    method @Deprecated public abstract long getSize() throws java.io.IOException;
+    method @Deprecated public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
-  public class FileMediaItem extends androidx.media2.common.MediaItem {
-    method public long getFileDescriptorLength();
-    method public long getFileDescriptorOffset();
-    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
-    field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+  @Deprecated public class FileMediaItem extends androidx.media2.common.MediaItem {
+    method @Deprecated public long getFileDescriptorLength();
+    method @Deprecated public long getFileDescriptorOffset();
+    method @Deprecated public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+    field @Deprecated public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
   }
 
-  public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
-    ctor public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
-    method public androidx.media2.common.FileMediaItem build();
-    method public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
-    method public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
-    method public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
+  @Deprecated public static final class FileMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+    ctor @Deprecated public FileMediaItem.Builder(android.os.ParcelFileDescriptor);
+    method @Deprecated public androidx.media2.common.FileMediaItem build();
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setFileDescriptorLength(long);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setFileDescriptorOffset(long);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.FileMediaItem.Builder setStartPosition(long);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class MediaItem extends androidx.versionedparcelable.CustomVersionedParcelable {
-    method public long getEndPosition();
-    method public androidx.media2.common.MediaMetadata? getMetadata();
-    method public long getStartPosition();
-    method public void setMetadata(androidx.media2.common.MediaMetadata?);
-    field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class MediaItem extends androidx.versionedparcelable.CustomVersionedParcelable {
+    method @Deprecated public long getEndPosition();
+    method @Deprecated public androidx.media2.common.MediaMetadata? getMetadata();
+    method @Deprecated public long getStartPosition();
+    method @Deprecated public void setMetadata(androidx.media2.common.MediaMetadata?);
+    field @Deprecated public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
   }
 
-  public static class MediaItem.Builder {
-    ctor public MediaItem.Builder();
-    method public androidx.media2.common.MediaItem build();
-    method public androidx.media2.common.MediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.MediaItem.Builder setStartPosition(long);
+  @Deprecated public static class MediaItem.Builder {
+    ctor @Deprecated public MediaItem.Builder();
+    method @Deprecated public androidx.media2.common.MediaItem build();
+    method @Deprecated public androidx.media2.common.MediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.MediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.MediaItem.Builder setStartPosition(long);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public final class MediaMetadata extends androidx.versionedparcelable.CustomVersionedParcelable {
-    method public boolean containsKey(String);
-    method public android.graphics.Bitmap? getBitmap(String);
-    method public android.os.Bundle? getExtras();
-    method public float getFloat(String);
-    method public long getLong(String);
-    method public String? getMediaId();
-    method public androidx.media2.common.Rating? getRating(String);
-    method public String? getString(String);
-    method public CharSequence? getText(String);
-    method public java.util.Set<java.lang.String!> keySet();
-    method public int size();
-    field public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
-    field public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
-    field public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
-    field public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
-    field public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
-    field public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
-    field public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
-    field public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
-    field public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
-    field public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
-    field public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
-    field public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
-    field public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
-    field public static final String METADATA_KEY_ART = "android.media.metadata.ART";
-    field public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
-    field public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
-    field public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
-    field public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
-    field public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
-    field public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
-    field public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
-    field public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
-    field public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
-    field public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
-    field public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
-    field public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
-    field public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
-    field public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
-    field public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
-    field public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
-    field public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
-    field public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
-    field public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
-    field public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
-    field public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
-    field public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
-    field public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
-    field public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
-    field public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
-    field public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
-    field public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
-    field public static final long STATUS_DOWNLOADED = 2L; // 0x2L
-    field public static final long STATUS_DOWNLOADING = 1L; // 0x1L
-    field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public final class MediaMetadata extends androidx.versionedparcelable.CustomVersionedParcelable {
+    method @Deprecated public boolean containsKey(String);
+    method @Deprecated public android.graphics.Bitmap? getBitmap(String);
+    method @Deprecated public android.os.Bundle? getExtras();
+    method @Deprecated public float getFloat(String);
+    method @Deprecated public long getLong(String);
+    method @Deprecated public String? getMediaId();
+    method @Deprecated public androidx.media2.common.Rating? getRating(String);
+    method @Deprecated public String? getString(String);
+    method @Deprecated public CharSequence? getText(String);
+    method @Deprecated public java.util.Set<java.lang.String!> keySet();
+    method @Deprecated public int size();
+    field @Deprecated public static final long BROWSABLE_TYPE_ALBUMS = 2L; // 0x2L
+    field @Deprecated public static final long BROWSABLE_TYPE_ARTISTS = 3L; // 0x3L
+    field @Deprecated public static final long BROWSABLE_TYPE_GENRES = 4L; // 0x4L
+    field @Deprecated public static final long BROWSABLE_TYPE_MIXED = 0L; // 0x0L
+    field @Deprecated public static final long BROWSABLE_TYPE_NONE = -1L; // 0xffffffffffffffffL
+    field @Deprecated public static final long BROWSABLE_TYPE_PLAYLISTS = 5L; // 0x5L
+    field @Deprecated public static final long BROWSABLE_TYPE_TITLES = 1L; // 0x1L
+    field @Deprecated public static final long BROWSABLE_TYPE_YEARS = 6L; // 0x6L
+    field @Deprecated public static final String METADATA_KEY_ADVERTISEMENT = "androidx.media2.metadata.ADVERTISEMENT";
+    field @Deprecated public static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
+    field @Deprecated public static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
+    field @Deprecated public static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+    field @Deprecated public static final String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
+    field @Deprecated public static final String METADATA_KEY_ART = "android.media.metadata.ART";
+    field @Deprecated public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
+    field @Deprecated public static final String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
+    field @Deprecated public static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+    field @Deprecated public static final String METADATA_KEY_BROWSABLE = "androidx.media2.metadata.BROWSABLE";
+    field @Deprecated public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+    field @Deprecated public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
+    field @Deprecated public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
+    field @Deprecated public static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
+    field @Deprecated public static final String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
+    field @Deprecated public static final String METADATA_KEY_DOWNLOAD_STATUS = "androidx.media2.metadata.DOWNLOAD_STATUS";
+    field @Deprecated public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
+    field @Deprecated public static final String METADATA_KEY_EXTRAS = "androidx.media2.metadata.EXTRAS";
+    field @Deprecated public static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+    field @Deprecated public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+    field @Deprecated public static final String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
+    field @Deprecated public static final String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
+    field @Deprecated public static final String METADATA_KEY_PLAYABLE = "androidx.media2.metadata.PLAYABLE";
+    field @Deprecated public static final String METADATA_KEY_RATING = "android.media.metadata.RATING";
+    field @Deprecated public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
+    field @Deprecated public static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+    field @Deprecated public static final String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
+    field @Deprecated public static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
+    field @Deprecated public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
+    field @Deprecated public static final long STATUS_DOWNLOADED = 2L; // 0x2L
+    field @Deprecated public static final long STATUS_DOWNLOADING = 1L; // 0x1L
+    field @Deprecated public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
   }
 
-  public static final class MediaMetadata.Builder {
-    ctor public MediaMetadata.Builder();
-    ctor public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
-    method public androidx.media2.common.MediaMetadata build();
-    method public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
-    method public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
-    method public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
-    method public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
-    method public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
-    method public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
-    method public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
+  @Deprecated public static final class MediaMetadata.Builder {
+    ctor @Deprecated public MediaMetadata.Builder();
+    ctor @Deprecated public MediaMetadata.Builder(androidx.media2.common.MediaMetadata);
+    method @Deprecated public androidx.media2.common.MediaMetadata build();
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putBitmap(String, android.graphics.Bitmap?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putFloat(String, float);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putLong(String, long);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putRating(String, androidx.media2.common.Rating?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putString(String, String?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder putText(String, CharSequence?);
+    method @Deprecated public androidx.media2.common.MediaMetadata.Builder setExtras(android.os.Bundle?);
   }
 
-  public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
-    method public boolean isRated();
+  @Deprecated public interface Rating extends androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public boolean isRated();
   }
 
-  public abstract class SessionPlayer implements java.io.Closeable {
-    ctor public SessionPlayer();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
-    method @CallSuper public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
-    method public abstract long getBufferedPosition();
-    method public abstract int getBufferingState();
-    method protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
-    method public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
-    method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
-    method public abstract long getCurrentPosition();
-    method public abstract long getDuration();
-    method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
-    method public abstract float getPlaybackSpeed();
-    method public abstract int getPlayerState();
-    method public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
-    method public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
-    method @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
-    method public abstract int getRepeatMode();
-    method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
-    method public abstract int getShuffleMode();
-    method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
-    method public androidx.media2.common.VideoSize getVideoSize();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
-    method public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
-    method public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
-    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
-    field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
-    field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
-    field public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
-    field public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
-    field public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
-    field public static final int PLAYER_STATE_ERROR = 3; // 0x3
-    field public static final int PLAYER_STATE_IDLE = 0; // 0x0
-    field public static final int PLAYER_STATE_PAUSED = 1; // 0x1
-    field public static final int PLAYER_STATE_PLAYING = 2; // 0x2
-    field public static final int REPEAT_MODE_ALL = 2; // 0x2
-    field public static final int REPEAT_MODE_GROUP = 3; // 0x3
-    field public static final int REPEAT_MODE_NONE = 0; // 0x0
-    field public static final int REPEAT_MODE_ONE = 1; // 0x1
-    field public static final int SHUFFLE_MODE_ALL = 1; // 0x1
-    field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
-    field public static final int SHUFFLE_MODE_NONE = 0; // 0x0
-    field public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
+  @Deprecated public abstract class SessionPlayer implements java.io.Closeable {
+    ctor @Deprecated public SessionPlayer();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated @CallSuper public void close();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public abstract androidx.media.AudioAttributesCompat? getAudioAttributes();
+    method @Deprecated public abstract long getBufferedPosition();
+    method @Deprecated public abstract int getBufferingState();
+    method @Deprecated protected final java.util.List<androidx.core.util.Pair<androidx.media2.common.SessionPlayer.PlayerCallback!,java.util.concurrent.Executor!>!> getCallbacks();
+    method @Deprecated public abstract androidx.media2.common.MediaItem? getCurrentMediaItem();
+    method @Deprecated @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getCurrentMediaItemIndex();
+    method @Deprecated public abstract long getCurrentPosition();
+    method @Deprecated public abstract long getDuration();
+    method @Deprecated @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getNextMediaItemIndex();
+    method @Deprecated public abstract float getPlaybackSpeed();
+    method @Deprecated public abstract int getPlayerState();
+    method @Deprecated public abstract java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+    method @Deprecated public abstract androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+    method @Deprecated @IntRange(from=androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) public abstract int getPreviousMediaItemIndex();
+    method @Deprecated public abstract int getRepeatMode();
+    method @Deprecated public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+    method @Deprecated public abstract int getShuffleMode();
+    method @Deprecated public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+    method @Deprecated public androidx.media2.common.VideoSize getVideoSize();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+    method @Deprecated public final void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.common.SessionPlayer.PlayerCallback);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(float);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setSurface(android.view.Surface?);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+    method @Deprecated public final void unregisterPlayerCallback(androidx.media2.common.SessionPlayer.PlayerCallback);
+    method @Deprecated public abstract com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+    field @Deprecated public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
+    field @Deprecated public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
+    field @Deprecated public static final int BUFFERING_STATE_COMPLETE = 3; // 0x3
+    field @Deprecated public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
+    field @Deprecated public static final int INVALID_ITEM_INDEX = -1; // 0xffffffff
+    field @Deprecated public static final int PLAYER_STATE_ERROR = 3; // 0x3
+    field @Deprecated public static final int PLAYER_STATE_IDLE = 0; // 0x0
+    field @Deprecated public static final int PLAYER_STATE_PAUSED = 1; // 0x1
+    field @Deprecated public static final int PLAYER_STATE_PLAYING = 2; // 0x2
+    field @Deprecated public static final int REPEAT_MODE_ALL = 2; // 0x2
+    field @Deprecated public static final int REPEAT_MODE_GROUP = 3; // 0x3
+    field @Deprecated public static final int REPEAT_MODE_NONE = 0; // 0x0
+    field @Deprecated public static final int REPEAT_MODE_ONE = 1; // 0x1
+    field @Deprecated public static final int SHUFFLE_MODE_ALL = 1; // 0x1
+    field @Deprecated public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
+    field @Deprecated public static final int SHUFFLE_MODE_NONE = 0; // 0x0
+    field @Deprecated public static final long UNKNOWN_TIME = -9223372036854775808L; // 0x8000000000000000L
   }
 
-  public abstract static class SessionPlayer.PlayerCallback {
-    ctor public SessionPlayer.PlayerCallback();
-    method public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
-    method public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
-    method public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?);
-    method public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
-    method public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
-    method public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
-    method public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
-    method public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
-    method public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
-    method public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
-    method public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
-    method public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
-    method public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
-    method public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
+  @Deprecated public abstract static class SessionPlayer.PlayerCallback {
+    ctor @Deprecated public SessionPlayer.PlayerCallback();
+    method @Deprecated public void onAudioAttributesChanged(androidx.media2.common.SessionPlayer, androidx.media.AudioAttributesCompat?);
+    method @Deprecated public void onBufferingStateChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?, int);
+    method @Deprecated public void onCurrentMediaItemChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem?);
+    method @Deprecated public void onPlaybackCompleted(androidx.media2.common.SessionPlayer);
+    method @Deprecated public void onPlaybackSpeedChanged(androidx.media2.common.SessionPlayer, float);
+    method @Deprecated public void onPlayerStateChanged(androidx.media2.common.SessionPlayer, int);
+    method @Deprecated public void onPlaylistChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onPlaylistMetadataChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onRepeatModeChanged(androidx.media2.common.SessionPlayer, int);
+    method @Deprecated public void onSeekCompleted(androidx.media2.common.SessionPlayer, long);
+    method @Deprecated public void onShuffleModeChanged(androidx.media2.common.SessionPlayer, int);
+    method @Deprecated public void onSubtitleData(androidx.media2.common.SessionPlayer, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+    method @Deprecated public void onTrackDeselected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTrackSelected(androidx.media2.common.SessionPlayer, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTracksChanged(androidx.media2.common.SessionPlayer, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+    method @Deprecated public void onVideoSizeChanged(androidx.media2.common.SessionPlayer, androidx.media2.common.VideoSize);
   }
 
-  public static class SessionPlayer.PlayerResult {
-    ctor public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
-    method public long getCompletionTime();
-    method public androidx.media2.common.MediaItem? getMediaItem();
-    method public int getResultCode();
+  @Deprecated public static class SessionPlayer.PlayerResult {
+    ctor @Deprecated public SessionPlayer.PlayerResult(int, androidx.media2.common.MediaItem?);
+    method @Deprecated public long getCompletionTime();
+    method @Deprecated public androidx.media2.common.MediaItem? getMediaItem();
+    method @Deprecated public int getResultCode();
     field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
     field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
     field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
@@ -226,47 +226,47 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public static class SessionPlayer.TrackInfo extends androidx.versionedparcelable.CustomVersionedParcelable {
-    ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
-    ctor public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
-    method public android.media.MediaFormat? getFormat();
-    method public int getId();
-    method public java.util.Locale getLanguage();
-    method public int getTrackType();
-    method public boolean isSelectable();
-    field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
-    field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
-    field public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
-    field public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public static class SessionPlayer.TrackInfo extends androidx.versionedparcelable.CustomVersionedParcelable {
+    ctor @Deprecated public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?);
+    ctor @Deprecated public SessionPlayer.TrackInfo(int, int, android.media.MediaFormat?, boolean);
+    method @Deprecated public android.media.MediaFormat? getFormat();
+    method @Deprecated public int getId();
+    method @Deprecated public java.util.Locale getLanguage();
+    method @Deprecated public int getTrackType();
+    method @Deprecated public boolean isSelectable();
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; // 0x4
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; // 0x0
+    field @Deprecated public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SubtitleData(long, long, byte[]);
-    method public byte[] getData();
-    method public long getDurationUs();
-    method public long getStartTimeUs();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class SubtitleData implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SubtitleData(long, long, byte[]);
+    method @Deprecated public byte[] getData();
+    method @Deprecated public long getDurationUs();
+    method @Deprecated public long getStartTimeUs();
   }
 
-  public class UriMediaItem extends androidx.media2.common.MediaItem {
-    method public android.net.Uri getUri();
-    method public java.util.List<java.net.HttpCookie!>? getUriCookies();
-    method public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
+  @Deprecated public class UriMediaItem extends androidx.media2.common.MediaItem {
+    method @Deprecated public android.net.Uri getUri();
+    method @Deprecated public java.util.List<java.net.HttpCookie!>? getUriCookies();
+    method @Deprecated public java.util.Map<java.lang.String!,java.lang.String!>? getUriHeaders();
   }
 
-  public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
-    ctor public UriMediaItem.Builder(android.net.Uri);
-    ctor public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
-    method public androidx.media2.common.UriMediaItem build();
-    method public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
-    method public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
-    method public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
+  @Deprecated public static final class UriMediaItem.Builder extends androidx.media2.common.MediaItem.Builder {
+    ctor @Deprecated public UriMediaItem.Builder(android.net.Uri);
+    ctor @Deprecated public UriMediaItem.Builder(android.net.Uri, java.util.Map<java.lang.String!,java.lang.String!>?, java.util.List<java.net.HttpCookie!>?);
+    method @Deprecated public androidx.media2.common.UriMediaItem build();
+    method @Deprecated public androidx.media2.common.UriMediaItem.Builder setEndPosition(long);
+    method @Deprecated public androidx.media2.common.UriMediaItem.Builder setMetadata(androidx.media2.common.MediaMetadata?);
+    method @Deprecated public androidx.media2.common.UriMediaItem.Builder setStartPosition(long);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
-    method @IntRange(from=0) public int getHeight();
-    method @IntRange(from=0) public int getWidth();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public class VideoSize implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public VideoSize(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @Deprecated @IntRange(from=0) public int getHeight();
+    method @Deprecated @IntRange(from=0) public int getWidth();
   }
 
 }
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/BaseResult.java b/media2/media2-common/src/main/java/androidx/media2/common/BaseResult.java
index ae43b7e..c446363 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/BaseResult.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/BaseResult.java
@@ -22,21 +22,27 @@
 import androidx.annotation.RestrictTo;
 
 /**
- * Base interface for all result classes in {@link androidx.media2.session.MediaSession},
- * {@link androidx.media2.session.MediaController},
- * and {@link SessionPlayer}, for defining result codes in one place with documentation.
+ * Base interface for all result classes in {@link androidx.media2.session.MediaSession}, {@link
+ * androidx.media2.session.MediaController}, and {@link SessionPlayer}, for defining result codes in
+ * one place with documentation.
+ *
  * <ul>
- *     <li>Error code: Negative integer</li>
- *     <li>Success code: 0</li>
- *     <li>Info code: Positive integer</li>
+ *   <li>Error code: Negative integer
+ *   <li>Success code: 0
+ *   <li>Info code: Positive integer
  * </ul>
+ *
  * <ul>
- *     <li>   0 <  |code| <  100: Session player specific code.</li>
- *     <li> 100 <= |code| <  500: Session/Controller specific code.</li>
- *     <li> 500 <= |code| < 1000: Browser/Library session specific code.</li>
- *     <li>1000 <= |code|       : Custom session player result code.</li>
+ *   <li>0 < |code| < 100: Session player specific code.
+ *   <li>100 <= |code| < 500: Session/Controller specific code.
+ *   <li>500 <= |code| < 1000: Browser/Library session specific code.
+ *   <li>1000 <= |code| : Custom session player result code.
  * </ul>
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @RestrictTo(LIBRARY_GROUP)
 public interface BaseResult {
     /**
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/CallbackMediaItem.java b/media2/media2-common/src/main/java/androidx/media2/common/CallbackMediaItem.java
index d9d444f..825f2fe 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/CallbackMediaItem.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/CallbackMediaItem.java
@@ -23,14 +23,17 @@
 
 /**
  * Structure for media item descriptor for {@link DataSourceCallback}.
- * <p>
- * Users should use {@link Builder} to create {@link CallbackMediaItem}.
- * <p>
- * You cannot directly send this object across the process through {@link ParcelUtils}. See
+ *
+ * <p>Users should use {@link Builder} to create {@link CallbackMediaItem}.
+ *
+ * <p>You cannot directly send this object across the process through {@link ParcelUtils}. See
  * {@link MediaItem} for detail.
  *
  * @see MediaItem
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class CallbackMediaItem extends MediaItem {
     private final DataSourceCallback mDataSourceCallback;
 
@@ -52,7 +55,11 @@
 
     /**
      * This Builder class simplifies the creation of a {@link CallbackMediaItem} object.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder extends MediaItem.Builder {
 
         @SuppressWarnings("WeakerAccess") /* synthetic access */
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/DataSourceCallback.java b/media2/media2-common/src/main/java/androidx/media2/common/DataSourceCallback.java
index aec577a..2f84969 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/DataSourceCallback.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/DataSourceCallback.java
@@ -26,13 +26,16 @@
  * For supplying media data, implement this if your app has special requirements for the way media
  * data is obtained.
  *
- * <p class="note">Methods of this interface may be called on multiple different
- * threads. There will be a thread synchronization point between each call to ensure that
- * modifications to the state of your DataSourceCallback are visible to future calls. This means
- * you don't need to do your own synchronization unless you're modifying the
- * DataSourceCallback from another thread while it's being used by the media library.</p>
+ * <p class="note">Methods of this interface may be called on multiple different threads. There will
+ * be a thread synchronization point between each call to ensure that modifications to the state of
+ * your DataSourceCallback are visible to future calls. This means you don't need to do your own
+ * synchronization unless you're modifying the DataSourceCallback from another thread while it's
+ * being used by the media library.
  *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public abstract class DataSourceCallback implements Closeable {
     /**
      * Called to request data from the given position.
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/FileMediaItem.java b/media2/media2-common/src/main/java/androidx/media2/common/FileMediaItem.java
index 344a02f..8d20a31 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/FileMediaItem.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/FileMediaItem.java
@@ -32,14 +32,17 @@
 
 /**
  * Structure for media item for a file.
- * <p>
- * Users should use {@link Builder} to create {@link FileMediaItem}.
- * <p>
- * You cannot directly send this object across the process through {@link ParcelUtils}. See
+ *
+ * <p>Users should use {@link Builder} to create {@link FileMediaItem}.
+ *
+ * <p>You cannot directly send this object across the process through {@link ParcelUtils}. See
  * {@link MediaItem} for detail.
  *
  * @see MediaItem
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class FileMediaItem extends MediaItem {
     private static final String TAG = "FileMediaItem";
     /**
@@ -159,7 +162,11 @@
 
     /**
      * This Builder class simplifies the creation of a {@link FileMediaItem} object.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder extends MediaItem.Builder {
 
         @SuppressWarnings("WeakerAccess") /* synthetic access */
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/MediaItem.java b/media2/media2-common/src/main/java/androidx/media2/common/MediaItem.java
index 5e9d413..c445435 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/MediaItem.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/MediaItem.java
@@ -39,27 +39,31 @@
 /**
  * A class with information on a single media item with the metadata information. Here are use
  * cases.
+ *
  * <ul>
- * <li>Specify media items to {@link SessionPlayer} for playback.
- * <li>Share media items across the processes.
+ *   <li>Specify media items to {@link SessionPlayer} for playback.
+ *   <li>Share media items across the processes.
  * </ul>
- * <p>
- * Subclasses of the session player may only accept certain subclasses of the media items. Check
+ *
+ * <p>Subclasses of the session player may only accept certain subclasses of the media items. Check
  * the player documentation that you're interested in.
- * <p>
- * When it's shared across the processes, we cannot guarantee that they contain the right values
+ *
+ * <p>When it's shared across the processes, we cannot guarantee that they contain the right values
  * because media items are application dependent especially for the metadata.
- * <p>
- * When an object of the {@link MediaItem}'s subclass is sent across the process between
- * {@link androidx.media2.session.MediaSession}/{@link androidx.media2.session.MediaController} or
- * {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession}/
- * {@link androidx.media2.session.MediaBrowser}, the
- * object will sent as if it's {@link MediaItem}. The recipient cannot get the object with the
- * subclasses' type. This will sanitize process specific information (e.g.
- * {@link java.io.FileDescriptor}, {@link android.content.Context}, etc).
- * <p>
- * This object is thread safe.
+ *
+ * <p>When an object of the {@link MediaItem}'s subclass is sent across the process between {@link
+ * androidx.media2.session.MediaSession}/{@link androidx.media2.session.MediaController} or {@link
+ * androidx.media2.session.MediaLibraryService.MediaLibrarySession}/ {@link
+ * androidx.media2.session.MediaBrowser}, the object will sent as if it's {@link MediaItem}. The
+ * recipient cannot get the object with the subclasses' type. This will sanitize process specific
+ * information (e.g. {@link java.io.FileDescriptor}, {@link android.content.Context}, etc).
+ *
+ * <p>This object is thread safe.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize(isCustom = true)
 public class MediaItem extends CustomVersionedParcelable {
     private static final String TAG = "MediaItem";
@@ -253,7 +257,11 @@
 
     /**
      * Builder for {@link MediaItem}.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static class Builder {
         @SuppressWarnings("WeakerAccess") /* synthetic access */
                 MediaMetadata mMetadata;
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/MediaMetadata.java b/media2/media2-common/src/main/java/androidx/media2/common/MediaMetadata.java
index 5bf8ef4..1959dc1 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/MediaMetadata.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/MediaMetadata.java
@@ -47,72 +47,80 @@
 /**
  * Contains metadata about an item, such as the title, artist, etc. This is optional, but you'd
  * better to provide this as much as possible when you're using media widget and/or session APIs.
- * <p>
- * The media widget components build its UI based on the metadata here. For an example,
- * {@link androidx.media2.widget.MediaControlView} will show title from the metadata.
- * <p>
- * The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require
- * some metadata values when it provides
- * {@link MediaItem}s to {@link androidx.media2.session.MediaBrowser}.
- * <p>
- * Topics covered here:
+ *
+ * <p>The media widget components build its UI based on the metadata here. For an example, {@link
+ * androidx.media2.widget.MediaControlView} will show title from the metadata.
+ *
+ * <p>The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require some
+ * metadata values when it provides {@link MediaItem}s to {@link
+ * androidx.media2.session.MediaBrowser}.
+ *
+ * <p>Topics covered here:
+ *
  * <ol>
- * <li><a href="#MediaId">Media ID</a>
- * <li><a href="#Browsable">Browsable type</a>
- * <li><a href="#Playable">Playable</a>
- * <li><a href="#Duration">Duration</a>
- * <li><a href="#UserRating">User rating</a>
+ *   <li><a href="#MediaId">Media ID</a>
+ *   <li><a href="#Browsable">Browsable type</a>
+ *   <li><a href="#Playable">Playable</a>
+ *   <li><a href="#Duration">Duration</a>
+ *   <li><a href="#UserRating">User rating</a>
  * </ol>
+ *
  * <h3 id="MediaId">{@link MediaMetadata#METADATA_KEY_MEDIA_ID Media ID}</h3>
- * <p>
- * If set, the media ID must be the persistent key for the underlying media contents, so
- * {@link androidx.media2.session.MediaController} and {@link androidx.media2.session.MediaBrowser}
- * can store the information and reuse it later. Some APIs requires a media ID (e.g.
- * {@link androidx.media2.session.MediaController#setRating}, so you'd better specify
- * one.
- * <p>
- * Typical example of using media ID is the URI of the contents, but use it with the caution because
- * the metadata is shared across the process in plain text.
- * <p>
- * The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require it
- * for the library root, so {@link androidx.media2.session.MediaBrowser} can call subsequent
- * {@link androidx.media2.session.MediaBrowser#getChildren} with the ID.
+ *
+ * <p>If set, the media ID must be the persistent key for the underlying media contents, so {@link
+ * androidx.media2.session.MediaController} and {@link androidx.media2.session.MediaBrowser} can
+ * store the information and reuse it later. Some APIs requires a media ID (e.g. {@link
+ * androidx.media2.session.MediaController#setRating}, so you'd better specify one.
+ *
+ * <p>Typical example of using media ID is the URI of the contents, but use it with the caution
+ * because the metadata is shared across the process in plain text.
+ *
+ * <p>The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require it
+ * for the library root, so {@link androidx.media2.session.MediaBrowser} can call subsequent {@link
+ * androidx.media2.session.MediaBrowser#getChildren} with the ID.
+ *
  * <h3 id="Browsable">{@link MediaMetadata#METADATA_KEY_BROWSABLE Browsable type}</h3>
- * <p>
- * Browsable defines whether the media item has children and type of children if any. With this,
- * {@link androidx.media2.session.MediaBrowser} can know whether the subsequent
- * {@link androidx.media2.session.MediaBrowser#getChildren} would successfully run.
- * <p>
- * The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require
- * the explicit browsable type for the media items returned by the
- * {@link
+ *
+ * <p>Browsable defines whether the media item has children and type of children if any. With this,
+ * {@link androidx.media2.session.MediaBrowser} can know whether the subsequent {@link
+ * androidx.media2.session.MediaBrowser#getChildren} would successfully run.
+ *
+ * <p>The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require the
+ * explicit browsable type for the media items returned by the {@link
  * androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback}.
+ *
  * <h3 id="Playable">{@link MediaMetadata#METADATA_KEY_PLAYABLE Playable type}</h3>
- * <p>
- * Playable defines whether the media item can be played or not. It may be possible for a playlist
- * to contain a media item which isn't playable in order to show a disabled media item.
- * <p>
- * The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require
- * the explicit playable value for the media items returned by the
- * {@link
+ *
+ * <p>Playable defines whether the media item can be played or not. It may be possible for a
+ * playlist to contain a media item which isn't playable in order to show a disabled media item.
+ *
+ * <p>The {@link androidx.media2.session.MediaLibraryService.MediaLibrarySession} would require the
+ * explicit playable value for the media items returned by the {@link
  * androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback}.
+ *
  * <h3 id="Duration">{@link MediaMetadata#METADATA_KEY_DURATION Duration}</h3>
+ *
  * The duration is the length of the contents. The {@link androidx.media2.session.MediaController}
  * can only get the duration through the metadata. This tells when would the playback ends, and also
  * tells about the allowed range of {@link androidx.media2.session.MediaController#seekTo(long)}.
- * <p>
- * If it's not set by developer, {@link androidx.media2.session.MediaSession} would update
- * the duration in the metadata with the {@link SessionPlayer#getDuration()}.
+ *
+ * <p>If it's not set by developer, {@link androidx.media2.session.MediaSession} would update the
+ * duration in the metadata with the {@link SessionPlayer#getDuration()}.
+ *
  * <h3 id="UserRating">{@link MediaMetadata#METADATA_KEY_USER_RATING User rating}</h3>
- * <p>
- * Prefer to have unrated user rating instead of {@code null}, so
- * {@link androidx.media2.session.MediaController} can know the possible user rating type
- * for calling {@link androidx.media2.session.MediaController#setRating(String, Rating)}.
+ *
+ * <p>Prefer to have unrated user rating instead of {@code null}, so {@link
+ * androidx.media2.session.MediaController} can know the possible user rating type for calling
+ * {@link androidx.media2.session.MediaController#setRating(String, Rating)}.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
 // New version of MediaMetadata with following changes
 //   - Don't implement Parcelable for updatable support.
 //   - Also support MediaDescription features. MediaDescription is deprecated instead because
 //     it was insufficient for controller to display media contents. (e.g. duration is missing)
+@Deprecated
 @VersionedParcelize(isCustom = true)
 public final class MediaMetadata extends CustomVersionedParcelable {
     private static final String TAG = "MediaMetadata";
@@ -982,9 +990,13 @@
     }
 
     /**
-     * Use to build MediaMetadatax objects. The system defined metadata keys must
-     * use the appropriate data type.
+     * Use to build MediaMetadatax objects. The system defined metadata keys must use the
+     * appropriate data type.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder {
         final Bundle mBundle;
 
@@ -1242,7 +1254,11 @@
 
     /**
      * Stores a bitmap and the matching key. Used for sending bitmaps to other process one-by-one.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     @VersionedParcelize
     static final class BitmapEntry implements VersionedParcelable {
         static final int BITMAP_SIZE_LIMIT_IN_BYTES = 256 * 1024; // 256 KB
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/Rating.java b/media2/media2-common/src/main/java/androidx/media2/common/Rating.java
index 6bfd8cd..f13f75d 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/Rating.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/Rating.java
@@ -20,7 +20,11 @@
 
 /**
  * An interface to encapsulate rating information used as content metadata.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public interface Rating extends VersionedParcelable {
     /**
      * Returns whether there is a rating value available.
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/SessionPlayer.java b/media2/media2-common/src/main/java/androidx/media2/common/SessionPlayer.java
index 3081607..4e75658 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/SessionPlayer.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/SessionPlayer.java
@@ -53,15 +53,16 @@
 
 /**
  * Base interface for all media players that want media session.
- * <p>
- * APIs that return {@link ListenableFuture} should be the asynchronous calls and shouldn't block
+ *
+ * <p>APIs that return {@link ListenableFuture} should be the asynchronous calls and shouldn't block
  * the calling thread. This guarantees the APIs are safe to be called on the main thread.
  *
  * <p>Topics covered here are:
+ *
  * <ol>
- * <li><a href="#BestPractices">Best practices</a>
- * <li><a href="#PlayerStates">Player states</a>
- * <li><a href="#InvalidStates">Invalid method calls</a>
+ *   <li><a href="#BestPractices">Best practices</a>
+ *   <li><a href="#PlayerStates">Player states</a>
+ *   <li><a href="#InvalidStates">Invalid method calls</a>
  * </ol>
  *
  * <h3 id="BestPractices">Best practices</h3>
@@ -69,80 +70,76 @@
  * Here are best practices when implementing/using SessionPlayer:
  *
  * <ul>
- * <li>When updating UI, you should respond to {@link PlayerCallback} invocations instead of
- * {@link PlayerResult} objects since the player can be controlled by others.
- * <li>When a SessionPlayer object is no longer being used, call {@link #close()} as soon as
- * possible to release the resources used by the internal player engine associated with the
- * SessionPlayer. For example, if a player uses hardware decoder, other player instances may
- * fallback to software decoders or fail to play. You cannot use SessionPlayer instance after
- * you call {@link #close()}. There is no way to reuse the instance.
- * <li>The current playback position can be retrieved with a call to {@link #getCurrentPosition()},
- * which is helpful for applications such as a music player that need to keep track of the playback
- * progress.
- * <li>The playback position can be adjusted with a call to {@link #seekTo(long)}. Although the
- * asynchronous {@link #seekTo} call returns right away, the actual seek operation may take a
- * while to finish, especially for audio/video being streamed.
- * <li>You can call {@link #seekTo(long)} from the {@link #PLAYER_STATE_PAUSED}. In these cases, if
- * you are playing a video stream and the requested position is valid, one video frame may be
- * displayed.
+ *   <li>When updating UI, you should respond to {@link PlayerCallback} invocations instead of
+ *       {@link PlayerResult} objects since the player can be controlled by others.
+ *   <li>When a SessionPlayer object is no longer being used, call {@link #close()} as soon as
+ *       possible to release the resources used by the internal player engine associated with the
+ *       SessionPlayer. For example, if a player uses hardware decoder, other player instances may
+ *       fallback to software decoders or fail to play. You cannot use SessionPlayer instance after
+ *       you call {@link #close()}. There is no way to reuse the instance.
+ *   <li>The current playback position can be retrieved with a call to {@link
+ *       #getCurrentPosition()}, which is helpful for applications such as a music player that need
+ *       to keep track of the playback progress.
+ *   <li>The playback position can be adjusted with a call to {@link #seekTo(long)}. Although the
+ *       asynchronous {@link #seekTo} call returns right away, the actual seek operation may take a
+ *       while to finish, especially for audio/video being streamed.
+ *   <li>You can call {@link #seekTo(long)} from the {@link #PLAYER_STATE_PAUSED}. In these cases,
+ *       if you are playing a video stream and the requested position is valid, one video frame may
+ *       be displayed.
  * </ul>
  *
  * <h3 id="PlayerStates">Player states</h3>
+ *
  * The playback control of audio/video files is managed as a state machine. The SessionPlayer
  * defines four states:
+ *
  * <ol>
- *     <li>{@link #PLAYER_STATE_IDLE}: Initial state after the instantiation.
- *         <p>
- *         While in this state, you should call {@link #setMediaItem(MediaItem)} or
- *         {@link #setPlaylist(List, MediaMetadata)}. Check returned {@link ListenableFuture} for
- *         potential error.
- *         <p>
- *         Calling {@link #prepare()} transfers this object to {@link #PLAYER_STATE_PAUSED}.
- *
- *     <li>{@link #PLAYER_STATE_PAUSED}: State when the audio/video playback is paused.
- *         <p>
- *         Call {@link #play()} to resume or start playback from the position where it paused.
- *
- *     <li>{@link #PLAYER_STATE_PLAYING}: State when the player plays the media item.
- *         <p>
- *         In this state, {@link PlayerCallback#onBufferingStateChanged(
- *         SessionPlayer, MediaItem, int)} will be called regularly to tell the buffering status.
- *         <p>
- *         Playback state would remain {@link #PLAYER_STATE_PLAYING} when the currently playing
- *         media item is changed.
- *         <p>
- *         When the playback reaches the end of stream, the behavior depends on repeat mode, set by
- *         {@link #setRepeatMode(int)}. If the repeat mode was set to {@link #REPEAT_MODE_NONE},
- *         the player will transfer to the {@link #PLAYER_STATE_PAUSED}. Otherwise, the
- *         SessionPlayer object remains in the {@link #PLAYER_STATE_PLAYING} and playback will be
- *         ongoing.
- *
- *     <li>{@link #PLAYER_STATE_ERROR}: State when the playback failed and player cannot be
- *         recovered by itself.
- *         <p>
- *         In general, playback might fail due to various reasons such as unsupported audio/video
- *         format, poorly interleaved audio/video, resolution too high, streaming timeout, and
- *         others. In addition, due to programming errors, a playback control operation might be
- *         performed from an <a href="#InvalidStates">invalid state</a>. In these cases the player
- *         may transition to this state.
+ *   <li>{@link #PLAYER_STATE_IDLE}: Initial state after the instantiation.
+ *       <p>While in this state, you should call {@link #setMediaItem(MediaItem)} or {@link
+ *       #setPlaylist(List, MediaMetadata)}. Check returned {@link ListenableFuture} for potential
+ *       error.
+ *       <p>Calling {@link #prepare()} transfers this object to {@link #PLAYER_STATE_PAUSED}.
+ *   <li>{@link #PLAYER_STATE_PAUSED}: State when the audio/video playback is paused.
+ *       <p>Call {@link #play()} to resume or start playback from the position where it paused.
+ *   <li>{@link #PLAYER_STATE_PLAYING}: State when the player plays the media item.
+ *       <p>In this state, {@link PlayerCallback#onBufferingStateChanged( SessionPlayer, MediaItem,
+ *       int)} will be called regularly to tell the buffering status.
+ *       <p>Playback state would remain {@link #PLAYER_STATE_PLAYING} when the currently playing
+ *       media item is changed.
+ *       <p>When the playback reaches the end of stream, the behavior depends on repeat mode, set by
+ *       {@link #setRepeatMode(int)}. If the repeat mode was set to {@link #REPEAT_MODE_NONE}, the
+ *       player will transfer to the {@link #PLAYER_STATE_PAUSED}. Otherwise, the SessionPlayer
+ *       object remains in the {@link #PLAYER_STATE_PLAYING} and playback will be ongoing.
+ *   <li>{@link #PLAYER_STATE_ERROR}: State when the playback failed and player cannot be recovered
+ *       by itself.
+ *       <p>In general, playback might fail due to various reasons such as unsupported audio/video
+ *       format, poorly interleaved audio/video, resolution too high, streaming timeout, and others.
+ *       In addition, due to programming errors, a playback control operation might be performed
+ *       from an <a href="#InvalidStates">invalid state</a>. In these cases the player may
+ *       transition to this state.
  * </ol>
+ *
  * Subclasses may have extra methods to reset the player state to {@link #PLAYER_STATE_IDLE} from
  * other states. Take a look at documentations of specific subclass that you're interested in.
+ *
  * <p>
  *
  * <h3 id="InvalidStates">Invalid method calls</h3>
- * The only method you safely call from the {@link #PLAYER_STATE_ERROR} is {@link #close()}.
- * Any other methods might return meaningless data.
- * <p>
- * Subclasses of the SessionPlayer may have extra methods that are safe to be called in the error
+ *
+ * The only method you safely call from the {@link #PLAYER_STATE_ERROR} is {@link #close()}. Any
+ * other methods might return meaningless data.
+ *
+ * <p>Subclasses of the SessionPlayer may have extra methods that are safe to be called in the error
  * state and/or provide a method to recover from the error state. Take a look at documentations of
  * specific subclass that you're interested in.
+ *
+ * <p>Most methods can be called from any non-Error state. In case they're called in invalid state,
+ * the implementation should ignore and would return {@link PlayerResult} with {@link
+ * PlayerResult#RESULT_ERROR_INVALID_STATE}. The following table lists the methods that aren't
+ * guaranteed to successfully running if they're called from the associated invalid states.
+ *
  * <p>
- * Most methods can be called from any non-Error state. In case they're called in invalid state,
- * the implementation should ignore and would return {@link PlayerResult} with
- * {@link PlayerResult#RESULT_ERROR_INVALID_STATE}. The following table lists the methods that
- * aren't guaranteed to successfully running if they're called from the associated invalid states.
- * <p>
+ *
  * <table>
  * <tr><th>Method Name</th> <th>Invalid States</th></tr>
  * <tr><td>setAudioAttributes</td> <td>{Paused, Playing}</td></tr>
@@ -151,11 +148,15 @@
  * <tr><td>pause</td> <td>{Idle}</td></tr>
  * <tr><td>seekTo</td> <td>{Idle}</td></tr>
  * </table>
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
 // Previously MediaSessionCompat.Callback.
 // Players can extend this directly (e.g. MediaPlayer) or create wrapper and control underlying
 // player.
 // Preferably it can be interface, but API guideline requires to use abstract class.
+@Deprecated
 public abstract class SessionPlayer implements Closeable {
     private static final String TAG = "SessionPlayer";
 
@@ -1016,18 +1017,22 @@
     /**
      * Class for the player to return each audio/video/subtitle track's metadata.
      *
-     * Note: TrackInfo holds a MediaFormat instance, but only the following key-values will be
+     * <p>Note: TrackInfo holds a MediaFormat instance, but only the following key-values will be
      * supported when sending it over different processes:
+     *
      * <ul>
-     * <li>{@link MediaFormat#KEY_LANGUAGE}</li>
-     * <li>{@link MediaFormat#KEY_MIME}</li>
-     * <li>{@link MediaFormat#KEY_IS_FORCED_SUBTITLE}</li>
-     * <li>{@link MediaFormat#KEY_IS_AUTOSELECT}</li>
-     * <li>{@link MediaFormat#KEY_IS_DEFAULT}</li>
+     *   <li>{@link MediaFormat#KEY_LANGUAGE}
+     *   <li>{@link MediaFormat#KEY_MIME}
+     *   <li>{@link MediaFormat#KEY_IS_FORCED_SUBTITLE}
+     *   <li>{@link MediaFormat#KEY_IS_AUTOSELECT}
+     *   <li>{@link MediaFormat#KEY_IS_DEFAULT}
      * </ul>
      *
      * @see #getTracks
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     @VersionedParcelize(isCustom = true)
     public static class TrackInfo extends CustomVersionedParcelable {
         public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0;
@@ -1290,9 +1295,13 @@
     }
 
     /**
-     * A callback class to receive notifications for events on the session player. See
-     * {@link #registerPlayerCallback(Executor, PlayerCallback)} to register this callback.
+     * A callback class to receive notifications for events on the session player. See {@link
+     * #registerPlayerCallback(Executor, PlayerCallback)} to register this callback.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public abstract static class PlayerCallback {
         /**
          * Called when the state of the player has changed.
@@ -1509,17 +1518,23 @@
 
     /**
      * Result class of the asynchronous APIs.
+     *
+     * <p>Subclass may extend this class for providing more result and/or custom result code. For
+     * the custom result code, follow the convention below to avoid potential code duplication.
+     *
      * <p>
-     * Subclass may extend this class for providing more result and/or custom result code. For the
-     * custom result code, follow the convention below to avoid potential code duplication.
-     * <p>
+     *
      * <ul>
-     * <li>Predefined error code: Negative integers greater than -100. (i.e. -100 < code < 0)
-     * <li>Custom error code: Negative integers equal to or less than -1000. (i.e. code < -1000)
-     * <li>Predefined info code: Positive integers less than 100. (i.e. 0 < code < 100)
-     * <li>Custom Info code: Positive integers equal to or greater than 1000. (i.e. code > +1000)
+     *   <li>Predefined error code: Negative integers greater than -100. (i.e. -100 < code < 0)
+     *   <li>Custom error code: Negative integers equal to or less than -1000. (i.e. code < -1000)
+     *   <li>Predefined info code: Positive integers less than 100. (i.e. 0 < code < 100)
+     *   <li>Custom Info code: Positive integers equal to or greater than 1000. (i.e. code > +1000)
      * </ul>
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     @SuppressWarnings("HiddenSuperclass")
     public static class PlayerResult implements BaseResult {
         /**
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/SubtitleData.java b/media2/media2-common/src/main/java/androidx/media2/common/SubtitleData.java
index 0b33264..e6c71b5 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/SubtitleData.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/SubtitleData.java
@@ -27,24 +27,26 @@
 import java.util.concurrent.Executor;
 
 /**
- * Class encapsulating subtitle data, as received through the
- * {@link SessionPlayer.PlayerCallback#onSubtitleData} interface.
- * The subtitle data includes:
+ * Class encapsulating subtitle data, as received through the {@link
+ * SessionPlayer.PlayerCallback#onSubtitleData} interface. The subtitle data includes:
+ *
  * <ul>
- * <li> the start time (in microseconds) of the data</li>
- * <li> the duration (in microseconds) of the data</li>
- * <li> the actual data.</li>
+ *   <li>the start time (in microseconds) of the data
+ *   <li>the duration (in microseconds) of the data
+ *   <li>the actual data.
  * </ul>
- * The data is stored in a byte-array, and is encoded in one of the supported in-band
- * subtitle formats. The subtitle encoding is determined by the MIME type of the
- * {@link SessionPlayer.TrackInfo} of the subtitle track, one of
- * {@link android.media.MediaFormat#MIMETYPE_TEXT_CEA_608} or
- * {@link android.media.MediaFormat#MIMETYPE_TEXT_CEA_708}.
+ *
+ * The data is stored in a byte-array, and is encoded in one of the supported in-band subtitle
+ * formats. The subtitle encoding is determined by the MIME type of the {@link
+ * SessionPlayer.TrackInfo} of the subtitle track, one of {@link
+ * android.media.MediaFormat#MIMETYPE_TEXT_CEA_608} or {@link
+ * android.media.MediaFormat#MIMETYPE_TEXT_CEA_708}.
+ *
+ * <p>Here is an example of iterating over the tracks of a {@link SessionPlayer}, and checking which
+ * encoding is used for the subtitle tracks:
  *
  * <p>
- * Here is an example of iterating over the tracks of a {@link SessionPlayer}, and checking which
- * encoding is used for the subtitle tracks:
- * <p>
+ *
  * <pre class="prettyprint">
  * // Initialize instance of player that extends SessionPlayer
  * SessionPlayerExtension player = new SessionPlayerExtension();
@@ -61,11 +63,16 @@
  *     }
  * }
  * </pre>
+ *
  * <p>
+ *
  * @see SessionPlayer#registerPlayerCallback(Executor, SessionPlayer.PlayerCallback)
  * @see SessionPlayer.PlayerCallback#onSubtitleData(SessionPlayer, MediaItem,
- *      SessionPlayer.TrackInfo, SubtitleData)
+ *     SessionPlayer.TrackInfo, SubtitleData)
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class SubtitleData implements VersionedParcelable {
     private static final String TAG = "SubtitleData";
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/UriMediaItem.java b/media2/media2-common/src/main/java/androidx/media2/common/UriMediaItem.java
index f8e4f95..5e2273c 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/UriMediaItem.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/UriMediaItem.java
@@ -33,14 +33,17 @@
 
 /**
  * Structure for media item descriptor for {@link Uri}.
- * <p>
- * Users should use {@link Builder} to create {@link UriMediaItem}.
- * <p>
- * You cannot directly send this object across the process through {@link ParcelUtils}. See
+ *
+ * <p>Users should use {@link Builder} to create {@link UriMediaItem}.
+ *
+ * <p>You cannot directly send this object across the process through {@link ParcelUtils}. See
  * {@link MediaItem} for detail.
  *
  * @see MediaItem
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class UriMediaItem extends MediaItem {
     private final Uri mUri;
     private final Map<String, String> mUriHeader;
@@ -88,7 +91,11 @@
 
     /**
      * This Builder class simplifies the creation of a {@link UriMediaItem} object.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder extends MediaItem.Builder {
 
         @SuppressWarnings("WeakerAccess") /* synthetic access */
diff --git a/media2/media2-common/src/main/java/androidx/media2/common/VideoSize.java b/media2/media2-common/src/main/java/androidx/media2/common/VideoSize.java
index 3a6254c..b14546f 100644
--- a/media2/media2-common/src/main/java/androidx/media2/common/VideoSize.java
+++ b/media2/media2-common/src/main/java/androidx/media2/common/VideoSize.java
@@ -25,7 +25,11 @@
 
 /**
  * Immutable class for describing video size.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public class VideoSize implements VersionedParcelable {
     @ParcelField(1)
diff --git a/media2/media2-player/api/current.txt b/media2/media2-player/api/current.txt
index c5e968d..0b2be00 100644
--- a/media2/media2-player/api/current.txt
+++ b/media2/media2-player/api/current.txt
@@ -1,122 +1,122 @@
 // Signature format: 4.0
 package androidx.media2.player {
 
-  public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
-    ctor public MediaPlayer(android.content.Context);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
-    method public androidx.media.AudioAttributesCompat? getAudioAttributes();
-    method public int getAudioSessionId();
-    method public long getBufferedPosition();
-    method public int getBufferingState();
-    method public androidx.media2.common.MediaItem? getCurrentMediaItem();
-    method public int getCurrentMediaItemIndex();
-    method public long getCurrentPosition();
-    method public long getDuration();
-    method public float getMaxPlayerVolume();
-    method public int getNextMediaItemIndex();
-    method public androidx.media2.player.PlaybackParams getPlaybackParams();
-    method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
-    method public int getPlayerState();
-    method public float getPlayerVolume();
-    method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
-    method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
-    method public int getPreviousMediaItemIndex();
-    method public int getRepeatMode();
-    method public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
-    method public int getShuffleMode();
-    method public androidx.media2.player.MediaTimestamp? getTimestamp();
+  @Deprecated public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
+    ctor @Deprecated public MediaPlayer(android.content.Context);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
+    method @Deprecated public androidx.media.AudioAttributesCompat? getAudioAttributes();
+    method @Deprecated public int getAudioSessionId();
+    method @Deprecated public long getBufferedPosition();
+    method @Deprecated public int getBufferingState();
+    method @Deprecated public androidx.media2.common.MediaItem? getCurrentMediaItem();
+    method @Deprecated public int getCurrentMediaItemIndex();
+    method @Deprecated public long getCurrentPosition();
+    method @Deprecated public long getDuration();
+    method @Deprecated public float getMaxPlayerVolume();
+    method @Deprecated public int getNextMediaItemIndex();
+    method @Deprecated public androidx.media2.player.PlaybackParams getPlaybackParams();
+    method @Deprecated @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
+    method @Deprecated public int getPlayerState();
+    method @Deprecated public float getPlayerVolume();
+    method @Deprecated public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+    method @Deprecated public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+    method @Deprecated public int getPreviousMediaItemIndex();
+    method @Deprecated public int getRepeatMode();
+    method @Deprecated public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
+    method @Deprecated public int getShuffleMode();
+    method @Deprecated public androidx.media2.player.MediaTimestamp? getTimestamp();
     method @Deprecated public java.util.List<androidx.media2.player.MediaPlayer.TrackInfo!> getTrackInfo();
-    method public androidx.media2.player.VideoSize getVideoSize();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
-    method public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
-    method public void reset();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
+    method @Deprecated public androidx.media2.player.VideoSize getVideoSize();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+    method @Deprecated public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated public void reset();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
     method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.player.MediaPlayer.TrackInfo);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
-    method public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
-    field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
-    field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
-    field public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
-    field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
-    field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
-    field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
-    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
-    field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+    method @Deprecated public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+    field @Deprecated public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
+    field @Deprecated public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
+    field @Deprecated public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
+    field @Deprecated public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
+    field @Deprecated public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+    field @Deprecated public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
+    field @Deprecated public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
+    field @Deprecated public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field @Deprecated public static final int NO_TRACK_SELECTED = -2147483648; // 0x80000000
-    field public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
-    field public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
-    field public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
-    field public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
-    field public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
-    field public static final int SEEK_CLOSEST = 3; // 0x3
-    field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
-    field public static final int SEEK_NEXT_SYNC = 1; // 0x1
-    field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
+    field @Deprecated public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
+    field @Deprecated public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
+    field @Deprecated public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
+    field @Deprecated public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
+    field @Deprecated public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+    field @Deprecated public static final int SEEK_CLOSEST = 3; // 0x3
+    field @Deprecated public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
+    field @Deprecated public static final int SEEK_NEXT_SYNC = 1; // 0x1
+    field @Deprecated public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
-    ctor public MediaPlayer.PlayerCallback();
-    method public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
-    method public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
-    method public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
-    method public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
+  @Deprecated public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+    ctor @Deprecated public MediaPlayer.PlayerCallback();
+    method @Deprecated public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+    method @Deprecated public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+    method @Deprecated public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
+    method @Deprecated public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
     method @Deprecated public void onVideoSizeChanged(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.VideoSize);
   }
 
-  public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo implements androidx.versionedparcelable.VersionedParcelable {
+  @Deprecated public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo implements androidx.versionedparcelable.VersionedParcelable {
   }
 
-  public final class MediaTimestamp {
-    method public long getAnchorMediaTimeUs();
-    method public long getAnchorSystemNanoTime();
-    method public float getMediaClockRate();
-    field public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
+  @Deprecated public final class MediaTimestamp {
+    method @Deprecated public long getAnchorMediaTimeUs();
+    method @Deprecated public long getAnchorSystemNanoTime();
+    method @Deprecated public float getMediaClockRate();
+    field @Deprecated public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
   }
 
-  public final class PlaybackParams {
-    method public Integer? getAudioFallbackMode();
-    method public Float? getPitch();
-    method public Float? getSpeed();
-    field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
-    field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
-    field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
+  @Deprecated public final class PlaybackParams {
+    method @Deprecated public Integer? getAudioFallbackMode();
+    method @Deprecated public Float? getPitch();
+    method @Deprecated public Float? getSpeed();
+    field @Deprecated public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
+    field @Deprecated public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
+    field @Deprecated public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
   }
 
-  public static final class PlaybackParams.Builder {
-    ctor public PlaybackParams.Builder();
-    ctor public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
-    method public androidx.media2.player.PlaybackParams build();
-    method public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
-    method public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
-    method public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+  @Deprecated public static final class PlaybackParams.Builder {
+    ctor @Deprecated public PlaybackParams.Builder();
+    ctor @Deprecated public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
+    method @Deprecated public androidx.media2.player.PlaybackParams build();
+    method @Deprecated public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
+    method @Deprecated public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+    method @Deprecated public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
   }
 
-  public class TimedMetaData {
-    method public byte[]! getMetaData();
-    method public long getTimestamp();
+  @Deprecated public class TimedMetaData {
+    method @Deprecated public byte[]! getMetaData();
+    method @Deprecated public long getTimestamp();
   }
 
-  public final class VideoSize extends androidx.media2.common.VideoSize {
-    ctor public VideoSize(int, int);
+  @Deprecated public final class VideoSize extends androidx.media2.common.VideoSize {
+    ctor @Deprecated public VideoSize(int, int);
   }
 
 }
diff --git a/media2/media2-player/api/restricted_current.txt b/media2/media2-player/api/restricted_current.txt
index 36c803e..c999693 100644
--- a/media2/media2-player/api/restricted_current.txt
+++ b/media2/media2-player/api/restricted_current.txt
@@ -1,122 +1,122 @@
 // Signature format: 4.0
 package androidx.media2.player {
 
-  public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
-    ctor public MediaPlayer(android.content.Context);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
-    method public androidx.media.AudioAttributesCompat? getAudioAttributes();
-    method public int getAudioSessionId();
-    method public long getBufferedPosition();
-    method public int getBufferingState();
-    method public androidx.media2.common.MediaItem? getCurrentMediaItem();
-    method public int getCurrentMediaItemIndex();
-    method public long getCurrentPosition();
-    method public long getDuration();
-    method public float getMaxPlayerVolume();
-    method public int getNextMediaItemIndex();
-    method public androidx.media2.player.PlaybackParams getPlaybackParams();
-    method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
-    method public int getPlayerState();
-    method public float getPlayerVolume();
-    method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
-    method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
-    method public int getPreviousMediaItemIndex();
-    method public int getRepeatMode();
-    method public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
-    method public int getShuffleMode();
-    method public androidx.media2.player.MediaTimestamp? getTimestamp();
+  @Deprecated public final class MediaPlayer extends androidx.media2.common.SessionPlayer {
+    ctor @Deprecated public MediaPlayer(android.content.Context);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> addPlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> attachAuxEffect(int);
+    method @Deprecated public androidx.media.AudioAttributesCompat? getAudioAttributes();
+    method @Deprecated public int getAudioSessionId();
+    method @Deprecated public long getBufferedPosition();
+    method @Deprecated public int getBufferingState();
+    method @Deprecated public androidx.media2.common.MediaItem? getCurrentMediaItem();
+    method @Deprecated public int getCurrentMediaItemIndex();
+    method @Deprecated public long getCurrentPosition();
+    method @Deprecated public long getDuration();
+    method @Deprecated public float getMaxPlayerVolume();
+    method @Deprecated public int getNextMediaItemIndex();
+    method @Deprecated public androidx.media2.player.PlaybackParams getPlaybackParams();
+    method @Deprecated @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) public float getPlaybackSpeed();
+    method @Deprecated public int getPlayerState();
+    method @Deprecated public float getPlayerVolume();
+    method @Deprecated public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+    method @Deprecated public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+    method @Deprecated public int getPreviousMediaItemIndex();
+    method @Deprecated public int getRepeatMode();
+    method @Deprecated public androidx.media2.player.MediaPlayer.TrackInfo? getSelectedTrack(int);
+    method @Deprecated public int getShuffleMode();
+    method @Deprecated public androidx.media2.player.MediaTimestamp? getTimestamp();
     method @Deprecated public java.util.List<androidx.media2.player.MediaPlayer.TrackInfo!> getTrackInfo();
-    method public androidx.media2.player.VideoSize getVideoSize();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
-    method public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
-    method public void reset();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
+    method @Deprecated public androidx.media2.player.VideoSize getVideoSize();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> pause();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> play();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> prepare();
+    method @Deprecated public void registerPlayerCallback(java.util.concurrent.Executor, androidx.media2.player.MediaPlayer.PlayerCallback);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> removePlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> replacePlaylistItem(int, androidx.media2.common.MediaItem);
+    method @Deprecated public void reset();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> seekTo(long, int);
     method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> selectTrack(androidx.media2.player.MediaPlayer.TrackInfo);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
-    method public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
-    field public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
-    field public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
-    field public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
-    field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
-    field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
-    field public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
-    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
-    field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioAttributes(androidx.media.AudioAttributesCompat);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAudioSessionId(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setAuxEffectSendLevel(@FloatRange(from=0, to=1) float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setMediaItem(androidx.media2.common.MediaItem);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackParams(androidx.media2.player.PlaybackParams);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaybackSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlayerVolume(@FloatRange(from=0, to=1) float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setPlaylist(java.util.List<androidx.media2.common.MediaItem!>, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setRepeatMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> setShuffleMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToNextPlaylistItem();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> skipToPreviousPlaylistItem();
+    method @Deprecated public void unregisterPlayerCallback(androidx.media2.player.MediaPlayer.PlayerCallback);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.common.SessionPlayer.PlayerResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+    field @Deprecated public static final int MEDIA_INFO_AUDIO_NOT_PLAYING = 804; // 0x324
+    field @Deprecated public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; // 0x320
+    field @Deprecated public static final int MEDIA_INFO_BUFFERING_UPDATE = 704; // 0x2c0
+    field @Deprecated public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
+    field @Deprecated public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+    field @Deprecated public static final int MEDIA_INFO_VIDEO_NOT_PLAYING = 805; // 0x325
+    field @Deprecated public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
+    field @Deprecated public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field @Deprecated public static final int NO_TRACK_SELECTED = -2147483648; // 0x80000000
-    field public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
-    field public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
-    field public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
-    field public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
-    field public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
-    field public static final int SEEK_CLOSEST = 3; // 0x3
-    field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
-    field public static final int SEEK_NEXT_SYNC = 1; // 0x1
-    field public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
+    field @Deprecated public static final int PLAYER_ERROR_IO = -1004; // 0xfffffc14
+    field @Deprecated public static final int PLAYER_ERROR_MALFORMED = -1007; // 0xfffffc11
+    field @Deprecated public static final int PLAYER_ERROR_TIMED_OUT = -110; // 0xffffff92
+    field @Deprecated public static final int PLAYER_ERROR_UNKNOWN = 1; // 0x1
+    field @Deprecated public static final int PLAYER_ERROR_UNSUPPORTED = -1010; // 0xfffffc0e
+    field @Deprecated public static final int SEEK_CLOSEST = 3; // 0x3
+    field @Deprecated public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
+    field @Deprecated public static final int SEEK_NEXT_SYNC = 1; // 0x1
+    field @Deprecated public static final int SEEK_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
-    ctor public MediaPlayer.PlayerCallback();
-    method public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
-    method public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
-    method public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
-    method public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
+  @Deprecated public abstract static class MediaPlayer.PlayerCallback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+    ctor @Deprecated public MediaPlayer.PlayerCallback();
+    method @Deprecated public void onError(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+    method @Deprecated public void onInfo(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, int, int);
+    method @Deprecated public void onMediaTimeDiscontinuity(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.MediaTimestamp);
+    method @Deprecated public void onTimedMetaDataAvailable(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.TimedMetaData);
     method @Deprecated public void onVideoSizeChanged(androidx.media2.player.MediaPlayer, androidx.media2.common.MediaItem, androidx.media2.player.VideoSize);
   }
 
-  public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo {
+  @Deprecated public static final class MediaPlayer.TrackInfo extends androidx.media2.common.SessionPlayer.TrackInfo {
   }
 
-  public final class MediaTimestamp {
-    method public long getAnchorMediaTimeUs();
-    method public long getAnchorSystemNanoTime();
-    method public float getMediaClockRate();
-    field public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
+  @Deprecated public final class MediaTimestamp {
+    method @Deprecated public long getAnchorMediaTimeUs();
+    method @Deprecated public long getAnchorSystemNanoTime();
+    method @Deprecated public float getMediaClockRate();
+    field @Deprecated public static final androidx.media2.player.MediaTimestamp TIMESTAMP_UNKNOWN;
   }
 
-  public final class PlaybackParams {
-    method public Integer? getAudioFallbackMode();
-    method public Float? getPitch();
-    method public Float? getSpeed();
-    field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
-    field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
-    field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
+  @Deprecated public final class PlaybackParams {
+    method @Deprecated public Integer? getAudioFallbackMode();
+    method @Deprecated public Float? getPitch();
+    method @Deprecated public Float? getSpeed();
+    field @Deprecated public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
+    field @Deprecated public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
+    field @Deprecated public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
   }
 
-  public static final class PlaybackParams.Builder {
-    ctor public PlaybackParams.Builder();
-    ctor public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
-    method public androidx.media2.player.PlaybackParams build();
-    method public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
-    method public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
-    method public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+  @Deprecated public static final class PlaybackParams.Builder {
+    ctor @Deprecated public PlaybackParams.Builder();
+    ctor @Deprecated public PlaybackParams.Builder(androidx.media2.player.PlaybackParams);
+    method @Deprecated public androidx.media2.player.PlaybackParams build();
+    method @Deprecated public androidx.media2.player.PlaybackParams.Builder setAudioFallbackMode(int);
+    method @Deprecated public androidx.media2.player.PlaybackParams.Builder setPitch(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
+    method @Deprecated public androidx.media2.player.PlaybackParams.Builder setSpeed(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE, fromInclusive=false) float);
   }
 
-  public class TimedMetaData {
-    method public byte[]! getMetaData();
-    method public long getTimestamp();
+  @Deprecated public class TimedMetaData {
+    method @Deprecated public byte[]! getMetaData();
+    method @Deprecated public long getTimestamp();
   }
 
-  public final class VideoSize extends androidx.media2.common.VideoSize {
-    ctor public VideoSize(int, int);
+  @Deprecated public final class VideoSize extends androidx.media2.common.VideoSize {
+    ctor @Deprecated public VideoSize(int, int);
   }
 
 }
diff --git a/media2/media2-player/src/main/java/androidx/media2/player/MediaPlayer.java b/media2/media2-player/src/main/java/androidx/media2/player/MediaPlayer.java
index d8f8fee..aaf3953 100644
--- a/media2/media2-player/src/main/java/androidx/media2/player/MediaPlayer.java
+++ b/media2/media2-player/src/main/java/androidx/media2/player/MediaPlayer.java
@@ -76,19 +76,22 @@
 /**
  * A media player which plays {@link MediaItem}s. The details on playback control and player states
  * can be found in the documentation of the base class, {@link SessionPlayer}.
- * <p>
- * Topic covered here:
+ *
+ * <p>Topic covered here:
+ *
  * <ol>
- * <li><a href="#AudioFocusAndNoisyIntent">Audio focus and noisy intent</a>
+ *   <li><a href="#AudioFocusAndNoisyIntent">Audio focus and noisy intent</a>
  * </ol>
+ *
  * <h3 id="AudioFocusAndNoisyIntent">Audio focus and noisy intent</h3>
- * <p>
- * By default, {@link MediaPlayer} handles audio focus and noisy intent with
- * {@link AudioAttributesCompat} set to this player. You need to call
- * {@link #setAudioAttributes(AudioAttributesCompat)} set the audio attribute while in the
- * {@link #PLAYER_STATE_IDLE}.
- * <p>
- * Here's the table of automatic audio focus behavior with audio attributes.
+ *
+ * <p>By default, {@link MediaPlayer} handles audio focus and noisy intent with {@link
+ * AudioAttributesCompat} set to this player. You need to call {@link
+ * #setAudioAttributes(AudioAttributesCompat)} set the audio attribute while in the {@link
+ * #PLAYER_STATE_IDLE}.
+ *
+ * <p>Here's the table of automatic audio focus behavior with audio attributes.
+ *
  * <table summary="Audio focus handling overview">
  * <tr><th>Audio Attributes</th><th>Audio Focus Gain Type</th><th>Misc</th></tr>
  * <tr><td>{@link AudioAttributesCompat#USAGE_VOICE_COMMUNICATION_SIGNALLING}</td>
@@ -129,15 +132,20 @@
  *     <td>No audio focus handling, and sets the player volume to {@code 0}</td>
  *     <td>This is to handle error</td></tr>
  * </table>
+ *
+ * <p>If an {@link AudioAttributesCompat} is not specified by {@link #setAudioAttributes}, {@link
+ * #getAudioAttributes} will return {@code null} and the default audio focus behavior will follow
+ * the {@code null} case on the table above.
+ *
+ * <p>For more information about the audio focus, take a look at <a
+ * href="{@docRoot}guide/topics/media-apps/audio-focus.html">Managing audio focus</a>
+ *
  * <p>
- * If an {@link AudioAttributesCompat} is not specified by {@link #setAudioAttributes},
- * {@link #getAudioAttributes} will return {@code null} and the default audio focus behavior will
- * follow the {@code null} case on the table above.
- * <p>
- * For more information about the audio focus, take a look at
- * <a href="{@docRoot}guide/topics/media-apps/audio-focus.html">Managing audio focus</a>
- * <p>
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public final class MediaPlayer extends SessionPlayer {
     private static final String TAG = "MediaPlayer";
 
@@ -3479,7 +3487,11 @@
     /**
      * Interface definition for callbacks to be invoked when the player has the corresponding
      * events.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public abstract static class PlayerCallback extends SessionPlayer.PlayerCallback {
         /**
          * @deprecated Use
@@ -3590,7 +3602,10 @@
      * Class for the player to return each audio/video/subtitle track's metadata.
      *
      * @see #getTracks
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class TrackInfo extends SessionPlayer.TrackInfo {
         TrackInfo(SessionPlayer.TrackInfo infoInternal) {
             super(infoInternal.getId(), infoInternal.getTrackType(), infoInternal.getFormat(),
diff --git a/media2/media2-player/src/main/java/androidx/media2/player/MediaTimestamp.java b/media2/media2-player/src/main/java/androidx/media2/player/MediaTimestamp.java
index 890fc53..f3485fd 100644
--- a/media2/media2-player/src/main/java/androidx/media2/player/MediaTimestamp.java
+++ b/media2/media2-player/src/main/java/androidx/media2/player/MediaTimestamp.java
@@ -19,22 +19,22 @@
 import androidx.annotation.NonNull;
 
 /**
- * An immutable object that represents the linear correlation between the media time
- * and the system time. It contains the media clock rate, together with the media timestamp
- * of an anchor frame and the system time when that frame was presented or is committed
- * to be presented.
- * <p>
- * The phrase "present" means that audio/video produced on device is detectable by an external
- * observer off device.
- * The time is based on the implementation's best effort, using whatever knowledge
- * is available to the system, but cannot account for any delay unknown to the implementation.
- * The anchor frame could be any frame, including a just-rendered frame, or even a theoretical
- * or in-between frame, based on the source of the MediaTimestamp.
- * When the anchor frame is a just-rendered one, the media time stands for
- * current position of the playback or recording.
+ * An immutable object that represents the linear correlation between the media time and the system
+ * time. It contains the media clock rate, together with the media timestamp of an anchor frame and
+ * the system time when that frame was presented or is committed to be presented.
+ *
+ * <p>The phrase "present" means that audio/video produced on device is detectable by an external
+ * observer off device. The time is based on the implementation's best effort, using whatever
+ * knowledge is available to the system, but cannot account for any delay unknown to the
+ * implementation. The anchor frame could be any frame, including a just-rendered frame, or even a
+ * theoretical or in-between frame, based on the source of the MediaTimestamp. When the anchor frame
+ * is a just-rendered one, the media time stands for current position of the playback or recording.
  *
  * @see MediaPlayer#getTimestamp
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public final class MediaTimestamp {
     /**
      * An unknown media timestamp value
diff --git a/media2/media2-player/src/main/java/androidx/media2/player/PlaybackParams.java b/media2/media2-player/src/main/java/androidx/media2/player/PlaybackParams.java
index 7f1be4a..b17f688 100644
--- a/media2/media2-player/src/main/java/androidx/media2/player/PlaybackParams.java
+++ b/media2/media2-player/src/main/java/androidx/media2/player/PlaybackParams.java
@@ -35,45 +35,49 @@
 /**
  * Structure for common playback params.
  *
- * Used by {@link MediaPlayer} {@link MediaPlayer#getPlaybackParams()} and
- * {@link MediaPlayer#setPlaybackParams(PlaybackParams)}
- * to control playback behavior.
- * <p>
- * PlaybackParams returned by {@link MediaPlayer#getPlaybackParams()} will always have values.
- * In case of {@link MediaPlayer#setPlaybackParams}, the player will not update the param if the
- * value is not set. For example, if pitch is set while speed is not set, only pitch will be
- * updated.
- * <p>
- * Note that the speed value does not change the player state. For example, if
- * {@link MediaPlayer#getPlaybackParams()} is called with the speed of 2.0f in
- * {@link MediaPlayer#PLAYER_STATE_PAUSED}, the player will just update internal property and stay
- * paused. Once {@link MediaPlayer#play()} is called afterwards, the player will start
- * playback with the given speed. Calling this with zero speed is not allowed.
- * <p>
- * <strong>audio fallback mode:</strong> select out-of-range parameter handling.
+ * <p>Used by {@link MediaPlayer} {@link MediaPlayer#getPlaybackParams()} and {@link
+ * MediaPlayer#setPlaybackParams(PlaybackParams)} to control playback behavior.
+ *
+ * <p>PlaybackParams returned by {@link MediaPlayer#getPlaybackParams()} will always have values. In
+ * case of {@link MediaPlayer#setPlaybackParams}, the player will not update the param if the value
+ * is not set. For example, if pitch is set while speed is not set, only pitch will be updated.
+ *
+ * <p>Note that the speed value does not change the player state. For example, if {@link
+ * MediaPlayer#getPlaybackParams()} is called with the speed of 2.0f in {@link
+ * MediaPlayer#PLAYER_STATE_PAUSED}, the player will just update internal property and stay paused.
+ * Once {@link MediaPlayer#play()} is called afterwards, the player will start playback with the
+ * given speed. Calling this with zero speed is not allowed.
+ *
+ * <p><strong>audio fallback mode:</strong> select out-of-range parameter handling.
+ *
  * <ul>
- * <li> {@link PlaybackParams#AUDIO_FALLBACK_MODE_DEFAULT}:
- *   System will determine best handling. </li>
- * <li> {@link PlaybackParams#AUDIO_FALLBACK_MODE_MUTE}:
- *   Play silence for params normally out of range.</li>
- * <li> {@link PlaybackParams#AUDIO_FALLBACK_MODE_FAIL}:
- *   Return {@link java.lang.IllegalArgumentException} from
- *   <code>AudioTrack.setPlaybackParams(PlaybackParams)</code>.</li>
+ *   <li>{@link PlaybackParams#AUDIO_FALLBACK_MODE_DEFAULT}: System will determine best handling.
+ *   <li>{@link PlaybackParams#AUDIO_FALLBACK_MODE_MUTE}: Play silence for params normally out of
+ *       range.
+ *   <li>{@link PlaybackParams#AUDIO_FALLBACK_MODE_FAIL}: Return {@link
+ *       java.lang.IllegalArgumentException} from <code>AudioTrack.setPlaybackParams(PlaybackParams)
+ *       </code>.
  * </ul>
- * <p> <strong>pitch:</strong> increases or decreases the tonal frequency of the audio content.
- * It is expressed as a multiplicative factor, where normal pitch is 1.0f.
- * <p> <strong>speed:</strong> increases or decreases the time to
- * play back a set of audio or video frames.
- * It is expressed as a multiplicative factor, where normal speed is 1.0f.
- * <p> Different combinations of speed and pitch may be used for audio playback;
- * some common ones:
+ *
+ * <p><strong>pitch:</strong> increases or decreases the tonal frequency of the audio content. It is
+ * expressed as a multiplicative factor, where normal pitch is 1.0f.
+ *
+ * <p><strong>speed:</strong> increases or decreases the time to play back a set of audio or video
+ * frames. It is expressed as a multiplicative factor, where normal speed is 1.0f.
+ *
+ * <p>Different combinations of speed and pitch may be used for audio playback; some common ones:
+ *
  * <ul>
- * <li> <em>Pitch equals 1.0f.</em> Speed change will be done with pitch preserved,
- * often called <em>timestretching</em>.</li>
- * <li> <em>Pitch equals speed.</em> Speed change will be done by <em>resampling</em>,
- * similar to {@link AudioTrack#setPlaybackRate(int)}.</li>
+ *   <li><em>Pitch equals 1.0f.</em> Speed change will be done with pitch preserved, often called
+ *       <em>timestretching</em>.
+ *   <li><em>Pitch equals speed.</em> Speed change will be done by <em>resampling</em>, similar to
+ *       {@link AudioTrack#setPlaybackRate(int)}.
  * </ul>
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public final class PlaybackParams {
     @RestrictTo(LIBRARY)
     @IntDef(
@@ -172,7 +176,11 @@
     /**
      * The builder class that makes it easy to chain setters to create a {@link PlaybackParams}
      * object.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder {
         private Integer mAudioFallbackMode;
         private Float mPitch;
diff --git a/media2/media2-player/src/main/java/androidx/media2/player/TimedMetaData.java b/media2/media2-player/src/main/java/androidx/media2/player/TimedMetaData.java
index d331750..fbf3ffd 100644
--- a/media2/media2-player/src/main/java/androidx/media2/player/TimedMetaData.java
+++ b/media2/media2-player/src/main/java/androidx/media2/player/TimedMetaData.java
@@ -24,12 +24,15 @@
  * Class that embodies one timed metadata access unit, including
  *
  * <ul>
- * <li> a time stamp, and </li>
- * <li> raw uninterpreted byte-array extracted directly from the container. </li>
+ *   <li>a time stamp, and
+ *   <li>raw uninterpreted byte-array extracted directly from the container.
  * </ul>
  *
  * @see MediaPlayer.PlayerCallback#onTimedMetaDataAvailable
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class TimedMetaData {
     private static final String TAG = "TimedMetaData";
 
diff --git a/media2/media2-player/src/main/java/androidx/media2/player/VideoSize.java b/media2/media2-player/src/main/java/androidx/media2/player/VideoSize.java
index d469c13..5aa2b31 100644
--- a/media2/media2-player/src/main/java/androidx/media2/player/VideoSize.java
+++ b/media2/media2-player/src/main/java/androidx/media2/player/VideoSize.java
@@ -20,7 +20,11 @@
 
 /**
  * Immutable class for describing video size.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public final class VideoSize extends androidx.media2.common.VideoSize {
     VideoSize(@NonNull androidx.media2.common.VideoSize internal) {
         super(internal.getWidth(), internal.getHeight());
diff --git a/media2/media2-session/api/current.txt b/media2/media2-session/api/current.txt
index 95e39e3..2855a88 100644
--- a/media2/media2-session/api/current.txt
+++ b/media2/media2-session/api/current.txt
@@ -1,22 +1,22 @@
 // Signature format: 4.0
 package androidx.media2.session {
 
-  public final class HeartRating implements androidx.media2.common.Rating {
-    ctor public HeartRating();
-    ctor public HeartRating(boolean);
-    method public boolean hasHeart();
-    method public boolean isRated();
+  @Deprecated public final class HeartRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public HeartRating();
+    ctor @Deprecated public HeartRating(boolean);
+    method @Deprecated public boolean hasHeart();
+    method @Deprecated public boolean isRated();
   }
 
-  public class LibraryResult implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public LibraryResult(int);
-    ctor public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    ctor public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public long getCompletionTime();
-    method public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
-    method public androidx.media2.common.MediaItem? getMediaItem();
-    method public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
-    method public int getResultCode();
+  @Deprecated public class LibraryResult implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public LibraryResult(int);
+    ctor @Deprecated public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    ctor @Deprecated public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public long getCompletionTime();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
+    method @Deprecated public androidx.media2.common.MediaItem? getMediaItem();
+    method @Deprecated public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
+    method @Deprecated public int getResultCode();
     field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
     field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
     field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
@@ -35,371 +35,371 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  public class MediaBrowser extends androidx.media2.session.MediaController {
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
+  @Deprecated public class MediaBrowser extends androidx.media2.session.MediaController {
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
   }
 
-  public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
-    ctor public MediaBrowser.BrowserCallback();
-    method public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+  @Deprecated public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
+    ctor @Deprecated public MediaBrowser.BrowserCallback();
+    method @Deprecated public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
   }
 
-  public static final class MediaBrowser.Builder {
-    ctor public MediaBrowser.Builder(android.content.Context);
-    method public androidx.media2.session.MediaBrowser build();
-    method public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
-    method public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
-    method public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
-    method public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
+  @Deprecated public static final class MediaBrowser.Builder {
+    ctor @Deprecated public MediaBrowser.Builder(android.content.Context);
+    method @Deprecated public androidx.media2.session.MediaBrowser build();
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
   }
 
-  public class MediaConstants {
-    field public static final String MEDIA_URI_AUTHORITY = "media2-session";
-    field public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
-    field public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
-    field public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
-    field public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
-    field public static final String MEDIA_URI_PATH_SET_MEDIA_URI = "setMediaUri";
-    field public static final String MEDIA_URI_QUERY_ID = "id";
-    field public static final String MEDIA_URI_QUERY_QUERY = "query";
-    field public static final String MEDIA_URI_QUERY_URI = "uri";
-    field public static final String MEDIA_URI_SCHEME = "androidx";
+  @Deprecated public class MediaConstants {
+    field @Deprecated public static final String MEDIA_URI_AUTHORITY = "media2-session";
+    field @Deprecated public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
+    field @Deprecated public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
+    field @Deprecated public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
+    field @Deprecated public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
+    field @Deprecated public static final String MEDIA_URI_PATH_SET_MEDIA_URI = "setMediaUri";
+    field @Deprecated public static final String MEDIA_URI_QUERY_ID = "id";
+    field @Deprecated public static final String MEDIA_URI_QUERY_QUERY = "query";
+    field @Deprecated public static final String MEDIA_URI_QUERY_URI = "uri";
+    field @Deprecated public static final String MEDIA_URI_SCHEME = "androidx";
   }
 
-  public class MediaController implements java.io.Closeable {
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
-    method public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
-    method public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
-    method public long getBufferedPosition();
-    method public int getBufferingState();
-    method public androidx.media2.session.SessionToken? getConnectedToken();
-    method public androidx.media2.common.MediaItem? getCurrentMediaItem();
-    method public int getCurrentMediaItemIndex();
-    method public long getCurrentPosition();
-    method public long getDuration();
-    method public int getNextMediaItemIndex();
-    method public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
-    method public float getPlaybackSpeed();
-    method public int getPlayerState();
-    method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
-    method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
-    method public int getPreviousMediaItemIndex();
-    method public int getRepeatMode();
-    method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
-    method public android.app.PendingIntent? getSessionActivity();
-    method public int getShuffleMode();
-    method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
-    method public androidx.media2.common.VideoSize getVideoSize();
-    method public boolean isConnected();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+  @Deprecated public class MediaController implements java.io.Closeable {
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
+    method @Deprecated public void close();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
+    method @Deprecated public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
+    method @Deprecated public long getBufferedPosition();
+    method @Deprecated public int getBufferingState();
+    method @Deprecated public androidx.media2.session.SessionToken? getConnectedToken();
+    method @Deprecated public androidx.media2.common.MediaItem? getCurrentMediaItem();
+    method @Deprecated public int getCurrentMediaItemIndex();
+    method @Deprecated public long getCurrentPosition();
+    method @Deprecated public long getDuration();
+    method @Deprecated public int getNextMediaItemIndex();
+    method @Deprecated public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
+    method @Deprecated public float getPlaybackSpeed();
+    method @Deprecated public int getPlayerState();
+    method @Deprecated public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+    method @Deprecated public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+    method @Deprecated public int getPreviousMediaItemIndex();
+    method @Deprecated public int getRepeatMode();
+    method @Deprecated public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+    method @Deprecated public android.app.PendingIntent? getSessionActivity();
+    method @Deprecated public int getShuffleMode();
+    method @Deprecated public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+    method @Deprecated public androidx.media2.common.VideoSize getVideoSize();
+    method @Deprecated public boolean isConnected();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
   }
 
-  public static final class MediaController.Builder {
-    ctor public MediaController.Builder(android.content.Context);
-    method public androidx.media2.session.MediaController build();
-    method public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
-    method public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
-    method public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
-    method public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
+  @Deprecated public static final class MediaController.Builder {
+    ctor @Deprecated public MediaController.Builder(android.content.Context);
+    method @Deprecated public androidx.media2.session.MediaController build();
+    method @Deprecated public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
+    method @Deprecated public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+    method @Deprecated public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
   }
 
-  public abstract static class MediaController.ControllerCallback {
-    ctor public MediaController.ControllerCallback();
-    method public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
-    method public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, int);
-    method public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
-    method public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
-    method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void onDisconnected(androidx.media2.session.MediaController);
-    method public void onPlaybackCompleted(androidx.media2.session.MediaController);
-    method public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
-    method public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
-    method public void onPlayerStateChanged(androidx.media2.session.MediaController, int);
-    method public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
-    method public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
-    method public void onRepeatModeChanged(androidx.media2.session.MediaController, int);
-    method public void onSeekCompleted(androidx.media2.session.MediaController, long);
-    method public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
-    method public void onShuffleModeChanged(androidx.media2.session.MediaController, int);
-    method public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
-    method public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
-    method public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
+  @Deprecated public abstract static class MediaController.ControllerCallback {
+    ctor @Deprecated public MediaController.ControllerCallback();
+    method @Deprecated public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, int);
+    method @Deprecated public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
+    method @Deprecated public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void onDisconnected(androidx.media2.session.MediaController);
+    method @Deprecated public void onPlaybackCompleted(androidx.media2.session.MediaController);
+    method @Deprecated public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
+    method @Deprecated public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
+    method @Deprecated public void onPlayerStateChanged(androidx.media2.session.MediaController, int);
+    method @Deprecated public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onRepeatModeChanged(androidx.media2.session.MediaController, int);
+    method @Deprecated public void onSeekCompleted(androidx.media2.session.MediaController, long);
+    method @Deprecated public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+    method @Deprecated public void onShuffleModeChanged(androidx.media2.session.MediaController, int);
+    method @Deprecated public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+    method @Deprecated public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+    method @Deprecated public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
   }
 
-  public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
-    method public androidx.media.AudioAttributesCompat? getAudioAttributes();
-    method public int getControlType();
-    method public int getCurrentVolume();
-    method public int getMaxVolume();
-    method public int getPlaybackType();
-    field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
-    field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+  @Deprecated public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public androidx.media.AudioAttributesCompat? getAudioAttributes();
+    method @Deprecated public int getControlType();
+    method @Deprecated public int getCurrentVolume();
+    method @Deprecated public int getMaxVolume();
+    method @Deprecated public int getPlaybackType();
+    field @Deprecated public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+    field @Deprecated public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
   }
 
-  public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
-    ctor public MediaLibraryService();
-    method public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
-    field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
+  @Deprecated public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
+    ctor @Deprecated public MediaLibraryService();
+    method @Deprecated public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+    field @Deprecated public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
   }
 
-  public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
-    method public android.os.Bundle? getExtras();
-    method public boolean isOffline();
-    method public boolean isRecent();
-    method public boolean isSuggested();
+  @Deprecated public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public android.os.Bundle? getExtras();
+    method @Deprecated public boolean isOffline();
+    method @Deprecated public boolean isRecent();
+    method @Deprecated public boolean isSuggested();
   }
 
-  public static final class MediaLibraryService.LibraryParams.Builder {
-    ctor public MediaLibraryService.LibraryParams.Builder();
-    method public androidx.media2.session.MediaLibraryService.LibraryParams build();
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
+  @Deprecated public static final class MediaLibraryService.LibraryParams.Builder {
+    ctor @Deprecated public MediaLibraryService.LibraryParams.Builder();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams build();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
   }
 
-  public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
-    method public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+  @Deprecated public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
+    method @Deprecated public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
   }
 
-  public static final class MediaLibraryService.MediaLibrarySession.Builder {
-    ctor public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
+  @Deprecated public static final class MediaLibraryService.MediaLibrarySession.Builder {
+    ctor @Deprecated public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
   }
 
-  public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
-    ctor public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
-    method public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
-    method public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+  @Deprecated public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
+    ctor @Deprecated public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
+    method @Deprecated public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+    method @Deprecated public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
   }
 
-  public class MediaSession implements java.io.Closeable {
-    method public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void close();
-    method public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
-    method public String getId();
-    method public androidx.media2.common.SessionPlayer getPlayer();
-    method public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
-    method public androidx.media2.session.SessionToken getToken();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
-    method public void updatePlayer(androidx.media2.common.SessionPlayer);
+  @Deprecated public class MediaSession implements java.io.Closeable {
+    method @Deprecated public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void close();
+    method @Deprecated public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
+    method @Deprecated public String getId();
+    method @Deprecated public androidx.media2.common.SessionPlayer getPlayer();
+    method @Deprecated public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
+    method @Deprecated public androidx.media2.session.SessionToken getToken();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+    method @Deprecated public void updatePlayer(androidx.media2.common.SessionPlayer);
   }
 
-  public static final class MediaSession.Builder {
-    ctor public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
-    method public androidx.media2.session.MediaSession build();
-    method public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
-    method public androidx.media2.session.MediaSession.Builder setId(String);
-    method public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
-    method public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
+  @Deprecated public static final class MediaSession.Builder {
+    ctor @Deprecated public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
+    method @Deprecated public androidx.media2.session.MediaSession build();
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setId(String);
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
   }
 
-  public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
-    method public androidx.media2.session.SessionCommand? getCommand();
-    method public CharSequence? getDisplayName();
-    method public android.os.Bundle? getExtras();
-    method public int getIconResId();
-    method public boolean isEnabled();
+  @Deprecated public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public androidx.media2.session.SessionCommand? getCommand();
+    method @Deprecated public CharSequence? getDisplayName();
+    method @Deprecated public android.os.Bundle? getExtras();
+    method @Deprecated public int getIconResId();
+    method @Deprecated public boolean isEnabled();
   }
 
-  public static final class MediaSession.CommandButton.Builder {
-    ctor public MediaSession.CommandButton.Builder();
-    method public androidx.media2.session.MediaSession.CommandButton build();
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
+  @Deprecated public static final class MediaSession.CommandButton.Builder {
+    ctor @Deprecated public MediaSession.CommandButton.Builder();
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton build();
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
   }
 
-  public static final class MediaSession.ControllerInfo {
-    method public android.os.Bundle getConnectionHints();
-    method public String getPackageName();
-    method public int getUid();
+  @Deprecated public static final class MediaSession.ControllerInfo {
+    method @Deprecated public android.os.Bundle getConnectionHints();
+    method @Deprecated public String getPackageName();
+    method @Deprecated public int getUid();
   }
 
-  public abstract static class MediaSession.SessionCallback {
-    ctor public MediaSession.SessionCallback();
-    method public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
-    method public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
-    method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
-    method public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
-    method public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+  @Deprecated public abstract static class MediaSession.SessionCallback {
+    ctor @Deprecated public MediaSession.SessionCallback();
+    method @Deprecated public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
+    method @Deprecated public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
+    method @Deprecated public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
+    method @Deprecated public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
   }
 
-  public final class MediaSessionManager {
-    method public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
-    method public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
+  @Deprecated public final class MediaSessionManager {
+    method @Deprecated public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
+    method @Deprecated public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
   }
 
-  public abstract class MediaSessionService extends android.app.Service {
-    ctor public MediaSessionService();
-    method public final void addSession(androidx.media2.session.MediaSession);
-    method public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
-    method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
-    method public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
-    method public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
-    method public final void removeSession(androidx.media2.session.MediaSession);
-    field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
+  @Deprecated public abstract class MediaSessionService extends android.app.Service {
+    ctor @Deprecated public MediaSessionService();
+    method @Deprecated public final void addSession(androidx.media2.session.MediaSession);
+    method @Deprecated public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
+    method @Deprecated @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+    method @Deprecated public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
+    method @Deprecated public final void removeSession(androidx.media2.session.MediaSession);
+    field @Deprecated public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
   }
 
-  public static class MediaSessionService.MediaNotification {
-    ctor public MediaSessionService.MediaNotification(int, android.app.Notification);
-    method public android.app.Notification getNotification();
-    method public int getNotificationId();
+  @Deprecated public static class MediaSessionService.MediaNotification {
+    ctor @Deprecated public MediaSessionService.MediaNotification(int, android.app.Notification);
+    method @Deprecated public android.app.Notification getNotification();
+    method @Deprecated public int getNotificationId();
   }
 
-  public final class PercentageRating implements androidx.media2.common.Rating {
-    ctor public PercentageRating();
-    ctor public PercentageRating(float);
-    method public float getPercentRating();
-    method public boolean isRated();
+  @Deprecated public final class PercentageRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public PercentageRating();
+    ctor @Deprecated public PercentageRating(float);
+    method @Deprecated public float getPercentRating();
+    method @Deprecated public boolean isRated();
   }
 
-  public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
-    ctor public RemoteSessionPlayer();
-    method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
-    method public abstract int getMaxVolume();
-    method public abstract int getVolume();
-    method public abstract int getVolumeControlType();
-    method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
-    field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
-    field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
-    field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+  @Deprecated public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
+    ctor @Deprecated public RemoteSessionPlayer();
+    method @Deprecated public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
+    method @Deprecated public abstract int getMaxVolume();
+    method @Deprecated public abstract int getVolume();
+    method @Deprecated public abstract int getVolumeControlType();
+    method @Deprecated public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
+    field @Deprecated public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+    field @Deprecated public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+    field @Deprecated public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
   }
 
-  public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
-    ctor public RemoteSessionPlayer.Callback();
-    method public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
+  @Deprecated public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+    ctor @Deprecated public RemoteSessionPlayer.Callback();
+    method @Deprecated public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
   }
 
-  public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionCommand(int);
-    ctor public SessionCommand(String, android.os.Bundle?);
-    method public int getCommandCode();
-    method public String? getCustomAction();
-    method public android.os.Bundle? getCustomExtras();
-    field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
-    field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
-    field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
-    field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
-    field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
-    field public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
-    field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
-    field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
-    field public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
-    field public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
-    field public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
-    field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
-    field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
-    field public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
-    field public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
-    field public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
-    field public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
-    field public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
-    field public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
-    field public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
-    field public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
-    field public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
-    field public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
-    field public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
-    field public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
-    field public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
-    field public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
-    field public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
-    field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
-    field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
-    field public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
-    field public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
-    field public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
-    field public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
-    field public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
-    field public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
-    field public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
-    field public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
-    field public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
-    field public static final int COMMAND_VERSION_1 = 1; // 0x1
-    field public static final int COMMAND_VERSION_2 = 2; // 0x2
+  @Deprecated public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionCommand(int);
+    ctor @Deprecated public SessionCommand(String, android.os.Bundle?);
+    method @Deprecated public int getCommandCode();
+    method @Deprecated public String? getCustomAction();
+    method @Deprecated public android.os.Bundle? getCustomExtras();
+    field @Deprecated public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
+    field @Deprecated public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
+    field @Deprecated public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
+    field @Deprecated public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
+    field @Deprecated public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
+    field @Deprecated public static final int COMMAND_VERSION_1 = 1; // 0x1
+    field @Deprecated public static final int COMMAND_VERSION_2 = 2; // 0x2
   }
 
-  public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionCommandGroup();
-    ctor public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
-    method public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
-    method public boolean hasCommand(androidx.media2.session.SessionCommand);
-    method public boolean hasCommand(int);
+  @Deprecated public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionCommandGroup();
+    ctor @Deprecated public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
+    method @Deprecated public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
+    method @Deprecated public boolean hasCommand(androidx.media2.session.SessionCommand);
+    method @Deprecated public boolean hasCommand(int);
   }
 
-  public static final class SessionCommandGroup.Builder {
-    ctor public SessionCommandGroup.Builder();
-    ctor public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
-    method public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
-    method public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
-    method public androidx.media2.session.SessionCommandGroup build();
-    method public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
+  @Deprecated public static final class SessionCommandGroup.Builder {
+    ctor @Deprecated public SessionCommandGroup.Builder();
+    ctor @Deprecated public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup build();
+    method @Deprecated public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
   }
 
-  public class SessionResult implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionResult(int, android.os.Bundle?);
-    method public long getCompletionTime();
-    method public android.os.Bundle? getCustomCommandResult();
-    method public androidx.media2.common.MediaItem? getMediaItem();
-    method public int getResultCode();
+  @Deprecated public class SessionResult implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionResult(int, android.os.Bundle?);
+    method @Deprecated public long getCompletionTime();
+    method @Deprecated public android.os.Bundle? getCustomCommandResult();
+    method @Deprecated public androidx.media2.common.MediaItem? getMediaItem();
+    method @Deprecated public int getResultCode();
     field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
     field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
     field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
@@ -415,34 +415,34 @@
     field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
     field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
     field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
-    field public static final int RESULT_SUCCESS = 0; // 0x0
+    field @Deprecated public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionToken(android.content.Context, android.content.ComponentName);
-    method public android.os.Bundle getExtras();
-    method public String getPackageName();
-    method public String? getServiceName();
-    method public int getType();
-    method public int getUid();
-    field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
-    field public static final int TYPE_SESSION = 0; // 0x0
-    field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+  @Deprecated public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionToken(android.content.Context, android.content.ComponentName);
+    method @Deprecated public android.os.Bundle getExtras();
+    method @Deprecated public String getPackageName();
+    method @Deprecated public String? getServiceName();
+    method @Deprecated public int getType();
+    method @Deprecated public int getUid();
+    field @Deprecated public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
+    field @Deprecated public static final int TYPE_SESSION = 0; // 0x0
+    field @Deprecated public static final int TYPE_SESSION_SERVICE = 1; // 0x1
   }
 
-  public final class StarRating implements androidx.media2.common.Rating {
-    ctor public StarRating(@IntRange(from=1) int);
-    ctor public StarRating(@IntRange(from=1) int, float);
-    method public int getMaxStars();
-    method public float getStarRating();
-    method public boolean isRated();
+  @Deprecated public final class StarRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public StarRating(@IntRange(from=1) int);
+    ctor @Deprecated public StarRating(@IntRange(from=1) int, float);
+    method @Deprecated public int getMaxStars();
+    method @Deprecated public float getStarRating();
+    method @Deprecated public boolean isRated();
   }
 
-  public final class ThumbRating implements androidx.media2.common.Rating {
-    ctor public ThumbRating();
-    ctor public ThumbRating(boolean);
-    method public boolean isRated();
-    method public boolean isThumbUp();
+  @Deprecated public final class ThumbRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public ThumbRating();
+    ctor @Deprecated public ThumbRating(boolean);
+    method @Deprecated public boolean isRated();
+    method @Deprecated public boolean isThumbUp();
   }
 
 }
diff --git a/media2/media2-session/api/restricted_current.txt b/media2/media2-session/api/restricted_current.txt
index 283a201..a7e3a862 100644
--- a/media2/media2-session/api/restricted_current.txt
+++ b/media2/media2-session/api/restricted_current.txt
@@ -1,22 +1,22 @@
 // Signature format: 4.0
 package androidx.media2.session {
 
-  @androidx.versionedparcelable.VersionedParcelize public final class HeartRating implements androidx.media2.common.Rating {
-    ctor public HeartRating();
-    ctor public HeartRating(boolean);
-    method public boolean hasHeart();
-    method public boolean isRated();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class HeartRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public HeartRating();
+    ctor @Deprecated public HeartRating(boolean);
+    method @Deprecated public boolean hasHeart();
+    method @Deprecated public boolean isRated();
   }
 
-  @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class LibraryResult extends androidx.versionedparcelable.CustomVersionedParcelable {
-    ctor public LibraryResult(int);
-    ctor public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    ctor public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public long getCompletionTime();
-    method public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
-    method public androidx.media2.common.MediaItem? getMediaItem();
-    method public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
-    method public int getResultCode();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class LibraryResult extends androidx.versionedparcelable.CustomVersionedParcelable {
+    ctor @Deprecated public LibraryResult(int);
+    ctor @Deprecated public LibraryResult(int, androidx.media2.common.MediaItem?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    ctor @Deprecated public LibraryResult(int, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public long getCompletionTime();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams? getLibraryParams();
+    method @Deprecated public androidx.media2.common.MediaItem? getMediaItem();
+    method @Deprecated public java.util.List<androidx.media2.common.MediaItem!>? getMediaItems();
+    method @Deprecated public int getResultCode();
     field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
     field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
     field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
@@ -35,371 +35,371 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  public class MediaBrowser extends androidx.media2.session.MediaController {
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
+  @Deprecated public class MediaBrowser extends androidx.media2.session.MediaController {
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getItem(String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getLibraryRoot(androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> search(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> subscribe(String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.LibraryResult!> unsubscribe(String);
   }
 
-  public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
-    ctor public MediaBrowser.BrowserCallback();
-    method public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+  @Deprecated public static class MediaBrowser.BrowserCallback extends androidx.media2.session.MediaController.ControllerCallback {
+    ctor @Deprecated public MediaBrowser.BrowserCallback();
+    method @Deprecated public void onChildrenChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public void onSearchResultChanged(androidx.media2.session.MediaBrowser, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
   }
 
-  public static final class MediaBrowser.Builder {
-    ctor public MediaBrowser.Builder(android.content.Context);
-    method public androidx.media2.session.MediaBrowser build();
-    method public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
-    method public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
-    method public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
-    method public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
+  @Deprecated public static final class MediaBrowser.Builder {
+    ctor @Deprecated public MediaBrowser.Builder(android.content.Context);
+    method @Deprecated public androidx.media2.session.MediaBrowser build();
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaBrowser.BrowserCallback);
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+    method @Deprecated public androidx.media2.session.MediaBrowser.Builder setSessionToken(androidx.media2.session.SessionToken);
   }
 
-  public class MediaConstants {
-    field public static final String MEDIA_URI_AUTHORITY = "media2-session";
-    field public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
-    field public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
-    field public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
-    field public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
-    field public static final String MEDIA_URI_PATH_SET_MEDIA_URI = "setMediaUri";
-    field public static final String MEDIA_URI_QUERY_ID = "id";
-    field public static final String MEDIA_URI_QUERY_QUERY = "query";
-    field public static final String MEDIA_URI_QUERY_URI = "uri";
-    field public static final String MEDIA_URI_SCHEME = "androidx";
+  @Deprecated public class MediaConstants {
+    field @Deprecated public static final String MEDIA_URI_AUTHORITY = "media2-session";
+    field @Deprecated public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId";
+    field @Deprecated public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch";
+    field @Deprecated public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId";
+    field @Deprecated public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch";
+    field @Deprecated public static final String MEDIA_URI_PATH_SET_MEDIA_URI = "setMediaUri";
+    field @Deprecated public static final String MEDIA_URI_QUERY_ID = "id";
+    field @Deprecated public static final String MEDIA_URI_QUERY_QUERY = "query";
+    field @Deprecated public static final String MEDIA_URI_QUERY_URI = "uri";
+    field @Deprecated public static final String MEDIA_URI_SCHEME = "androidx";
   }
 
-  public class MediaController implements java.io.Closeable {
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
-    method public void close();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
-    method public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
-    method public long getBufferedPosition();
-    method public int getBufferingState();
-    method public androidx.media2.session.SessionToken? getConnectedToken();
-    method public androidx.media2.common.MediaItem? getCurrentMediaItem();
-    method public int getCurrentMediaItemIndex();
-    method public long getCurrentPosition();
-    method public long getDuration();
-    method public int getNextMediaItemIndex();
-    method public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
-    method public float getPlaybackSpeed();
-    method public int getPlayerState();
-    method public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
-    method public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
-    method public int getPreviousMediaItemIndex();
-    method public int getRepeatMode();
-    method public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
-    method public android.app.PendingIntent? getSessionActivity();
-    method public int getShuffleMode();
-    method public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
-    method public androidx.media2.common.VideoSize getVideoSize();
-    method public boolean isConnected();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
+  @Deprecated public class MediaController implements java.io.Closeable {
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> addPlaylistItem(@IntRange(from=0) int, String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> adjustVolume(int, int);
+    method @Deprecated public void close();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> fastForward();
+    method @Deprecated public androidx.media2.session.SessionCommandGroup? getAllowedCommands();
+    method @Deprecated public long getBufferedPosition();
+    method @Deprecated public int getBufferingState();
+    method @Deprecated public androidx.media2.session.SessionToken? getConnectedToken();
+    method @Deprecated public androidx.media2.common.MediaItem? getCurrentMediaItem();
+    method @Deprecated public int getCurrentMediaItemIndex();
+    method @Deprecated public long getCurrentPosition();
+    method @Deprecated public long getDuration();
+    method @Deprecated public int getNextMediaItemIndex();
+    method @Deprecated public androidx.media2.session.MediaController.PlaybackInfo? getPlaybackInfo();
+    method @Deprecated public float getPlaybackSpeed();
+    method @Deprecated public int getPlayerState();
+    method @Deprecated public java.util.List<androidx.media2.common.MediaItem!>? getPlaylist();
+    method @Deprecated public androidx.media2.common.MediaMetadata? getPlaylistMetadata();
+    method @Deprecated public int getPreviousMediaItemIndex();
+    method @Deprecated public int getRepeatMode();
+    method @Deprecated public androidx.media2.common.SessionPlayer.TrackInfo? getSelectedTrack(int);
+    method @Deprecated public android.app.PendingIntent? getSessionActivity();
+    method @Deprecated public int getShuffleMode();
+    method @Deprecated public java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!> getTracks();
+    method @Deprecated public androidx.media2.common.VideoSize getVideoSize();
+    method @Deprecated public boolean isConnected();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> movePlaylistItem(@IntRange(from=0) int, @IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> pause();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> play();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> prepare();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> removePlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> replacePlaylistItem(@IntRange(from=0) int, String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> rewind();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> seekTo(long);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> selectTrack(androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaItem(String);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setMediaUri(android.net.Uri, android.os.Bundle?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaybackSpeed(float);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setPlaylist(java.util.List<java.lang.String!>, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRating(String, androidx.media2.common.Rating);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setRepeatMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setShuffleMode(int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setSurface(android.view.Surface?);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setVolumeTo(int, int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipBackward();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipForward();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToNextPlaylistItem();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPlaylistItem(@IntRange(from=0) int);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> skipToPreviousPlaylistItem();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> updatePlaylistMetadata(androidx.media2.common.MediaMetadata?);
   }
 
-  public static final class MediaController.Builder {
-    ctor public MediaController.Builder(android.content.Context);
-    method public androidx.media2.session.MediaController build();
-    method public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
-    method public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
-    method public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
-    method public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
+  @Deprecated public static final class MediaController.Builder {
+    ctor @Deprecated public MediaController.Builder(android.content.Context);
+    method @Deprecated public androidx.media2.session.MediaController build();
+    method @Deprecated public androidx.media2.session.MediaController.Builder setConnectionHints(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaController.Builder setControllerCallback(java.util.concurrent.Executor, androidx.media2.session.MediaController.ControllerCallback);
+    method @Deprecated public androidx.media2.session.MediaController.Builder setSessionCompatToken(android.support.v4.media.session.MediaSessionCompat.Token);
+    method @Deprecated public androidx.media2.session.MediaController.Builder setSessionToken(androidx.media2.session.SessionToken);
   }
 
-  public abstract static class MediaController.ControllerCallback {
-    ctor public MediaController.ControllerCallback();
-    method public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
-    method public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, int);
-    method public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
-    method public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
-    method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void onDisconnected(androidx.media2.session.MediaController);
-    method public void onPlaybackCompleted(androidx.media2.session.MediaController);
-    method public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
-    method public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
-    method public void onPlayerStateChanged(androidx.media2.session.MediaController, int);
-    method public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
-    method public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
-    method public void onRepeatModeChanged(androidx.media2.session.MediaController, int);
-    method public void onSeekCompleted(androidx.media2.session.MediaController, long);
-    method public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
-    method public void onShuffleModeChanged(androidx.media2.session.MediaController, int);
-    method public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
-    method public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
-    method public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
-    method public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
+  @Deprecated public abstract static class MediaController.ControllerCallback {
+    ctor @Deprecated public MediaController.ControllerCallback();
+    method @Deprecated public void onAllowedCommandsChanged(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public void onBufferingStateChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, int);
+    method @Deprecated public void onConnected(androidx.media2.session.MediaController, androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public void onCurrentMediaItemChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaItem?);
+    method @Deprecated public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaController, androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void onDisconnected(androidx.media2.session.MediaController);
+    method @Deprecated public void onPlaybackCompleted(androidx.media2.session.MediaController);
+    method @Deprecated public void onPlaybackInfoChanged(androidx.media2.session.MediaController, androidx.media2.session.MediaController.PlaybackInfo);
+    method @Deprecated public void onPlaybackSpeedChanged(androidx.media2.session.MediaController, float);
+    method @Deprecated public void onPlayerStateChanged(androidx.media2.session.MediaController, int);
+    method @Deprecated public void onPlaylistChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.MediaItem!>?, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onPlaylistMetadataChanged(androidx.media2.session.MediaController, androidx.media2.common.MediaMetadata?);
+    method @Deprecated public void onRepeatModeChanged(androidx.media2.session.MediaController, int);
+    method @Deprecated public void onSeekCompleted(androidx.media2.session.MediaController, long);
+    method @Deprecated public int onSetCustomLayout(androidx.media2.session.MediaController, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+    method @Deprecated public void onShuffleModeChanged(androidx.media2.session.MediaController, int);
+    method @Deprecated public void onSubtitleData(androidx.media2.session.MediaController, androidx.media2.common.MediaItem, androidx.media2.common.SessionPlayer.TrackInfo, androidx.media2.common.SubtitleData);
+    method @Deprecated public void onTrackDeselected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTrackSelected(androidx.media2.session.MediaController, androidx.media2.common.SessionPlayer.TrackInfo);
+    method @Deprecated public void onTracksChanged(androidx.media2.session.MediaController, java.util.List<androidx.media2.common.SessionPlayer.TrackInfo!>);
+    method @Deprecated public void onVideoSizeChanged(androidx.media2.session.MediaController, androidx.media2.common.VideoSize);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
-    method public androidx.media.AudioAttributesCompat? getAudioAttributes();
-    method public int getControlType();
-    method public int getCurrentVolume();
-    method public int getMaxVolume();
-    method public int getPlaybackType();
-    field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
-    field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public static final class MediaController.PlaybackInfo implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public androidx.media.AudioAttributesCompat? getAudioAttributes();
+    method @Deprecated public int getControlType();
+    method @Deprecated public int getCurrentVolume();
+    method @Deprecated public int getMaxVolume();
+    method @Deprecated public int getPlaybackType();
+    field @Deprecated public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+    field @Deprecated public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
   }
 
-  public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
-    ctor public MediaLibraryService();
-    method public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
-    field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
+  @Deprecated public abstract class MediaLibraryService extends androidx.media2.session.MediaSessionService {
+    ctor @Deprecated public MediaLibraryService();
+    method @Deprecated public abstract androidx.media2.session.MediaLibraryService.MediaLibrarySession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+    field @Deprecated public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
-    method public android.os.Bundle? getExtras();
-    method public boolean isOffline();
-    method public boolean isRecent();
-    method public boolean isSuggested();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public static final class MediaLibraryService.LibraryParams implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public android.os.Bundle? getExtras();
+    method @Deprecated public boolean isOffline();
+    method @Deprecated public boolean isRecent();
+    method @Deprecated public boolean isSuggested();
   }
 
-  public static final class MediaLibraryService.LibraryParams.Builder {
-    ctor public MediaLibraryService.LibraryParams.Builder();
-    method public androidx.media2.session.MediaLibraryService.LibraryParams build();
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
-    method public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
+  @Deprecated public static final class MediaLibraryService.LibraryParams.Builder {
+    ctor @Deprecated public MediaLibraryService.LibraryParams.Builder();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams build();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setExtras(android.os.Bundle?);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean);
   }
 
-  public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
-    method public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+  @Deprecated public static final class MediaLibraryService.MediaLibrarySession extends androidx.media2.session.MediaSession {
+    method @Deprecated public void notifyChildrenChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public void notifyChildrenChanged(String, int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public void notifySearchResultChanged(androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
   }
 
-  public static final class MediaLibraryService.MediaLibrarySession.Builder {
-    ctor public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
-    method public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
+  @Deprecated public static final class MediaLibraryService.MediaLibrarySession.Builder {
+    ctor @Deprecated public MediaLibraryService.MediaLibrarySession.Builder(androidx.media2.session.MediaLibraryService, androidx.media2.common.SessionPlayer, java.util.concurrent.Executor, androidx.media2.session.MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession build();
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setId(String);
+    method @Deprecated public androidx.media2.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent?);
   }
 
-  public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
-    ctor public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
-    method public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
-    method public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
-    method public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+  @Deprecated public static class MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback extends androidx.media2.session.MediaSession.SessionCallback {
+    ctor @Deprecated public MediaLibraryService.MediaLibrarySession.MediaLibrarySessionCallback();
+    method @Deprecated public androidx.media2.session.LibraryResult onGetChildren(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public androidx.media2.session.LibraryResult onGetItem(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
+    method @Deprecated public androidx.media2.session.LibraryResult onGetLibraryRoot(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public androidx.media2.session.LibraryResult onGetSearchResult(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public int onSearch(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public int onSubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.session.MediaLibraryService.LibraryParams?);
+    method @Deprecated public int onUnsubscribe(androidx.media2.session.MediaLibraryService.MediaLibrarySession, androidx.media2.session.MediaSession.ControllerInfo, String);
   }
 
-  public class MediaSession implements java.io.Closeable {
-    method public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void close();
-    method public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
-    method public String getId();
-    method public androidx.media2.common.SessionPlayer getPlayer();
-    method public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
-    method public androidx.media2.session.SessionToken getToken();
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
-    method public void updatePlayer(androidx.media2.common.SessionPlayer);
+  @Deprecated public class MediaSession implements java.io.Closeable {
+    method @Deprecated public void broadcastCustomCommand(androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void close();
+    method @Deprecated public java.util.List<androidx.media2.session.MediaSession.ControllerInfo!> getConnectedControllers();
+    method @Deprecated public String getId();
+    method @Deprecated public androidx.media2.common.SessionPlayer getPlayer();
+    method @Deprecated public android.support.v4.media.session.MediaSessionCompat.Token getSessionCompatToken();
+    method @Deprecated public androidx.media2.session.SessionToken getToken();
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> sendCustomCommand(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void setAllowedCommands(androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public com.google.common.util.concurrent.ListenableFuture<androidx.media2.session.SessionResult!> setCustomLayout(androidx.media2.session.MediaSession.ControllerInfo, java.util.List<androidx.media2.session.MediaSession.CommandButton!>);
+    method @Deprecated public void updatePlayer(androidx.media2.common.SessionPlayer);
   }
 
-  public static final class MediaSession.Builder {
-    ctor public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
-    method public androidx.media2.session.MediaSession build();
-    method public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
-    method public androidx.media2.session.MediaSession.Builder setId(String);
-    method public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
-    method public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
+  @Deprecated public static final class MediaSession.Builder {
+    ctor @Deprecated public MediaSession.Builder(android.content.Context, androidx.media2.common.SessionPlayer);
+    method @Deprecated public androidx.media2.session.MediaSession build();
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setExtras(android.os.Bundle);
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setId(String);
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent?);
+    method @Deprecated public androidx.media2.session.MediaSession.Builder setSessionCallback(java.util.concurrent.Executor, androidx.media2.session.MediaSession.SessionCallback);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
-    method public androidx.media2.session.SessionCommand? getCommand();
-    method public CharSequence? getDisplayName();
-    method public android.os.Bundle? getExtras();
-    method public int getIconResId();
-    method public boolean isEnabled();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public static final class MediaSession.CommandButton implements androidx.versionedparcelable.VersionedParcelable {
+    method @Deprecated public androidx.media2.session.SessionCommand? getCommand();
+    method @Deprecated public CharSequence? getDisplayName();
+    method @Deprecated public android.os.Bundle? getExtras();
+    method @Deprecated public int getIconResId();
+    method @Deprecated public boolean isEnabled();
   }
 
-  public static final class MediaSession.CommandButton.Builder {
-    ctor public MediaSession.CommandButton.Builder();
-    method public androidx.media2.session.MediaSession.CommandButton build();
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
-    method public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
+  @Deprecated public static final class MediaSession.CommandButton.Builder {
+    ctor @Deprecated public MediaSession.CommandButton.Builder();
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton build();
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setCommand(androidx.media2.session.SessionCommand?);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setDisplayName(CharSequence?);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setEnabled(boolean);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setExtras(android.os.Bundle?);
+    method @Deprecated public androidx.media2.session.MediaSession.CommandButton.Builder setIconResId(int);
   }
 
-  public static final class MediaSession.ControllerInfo {
-    method public android.os.Bundle getConnectionHints();
-    method public String getPackageName();
-    method public int getUid();
+  @Deprecated public static final class MediaSession.ControllerInfo {
+    method @Deprecated public android.os.Bundle getConnectionHints();
+    method @Deprecated public String getPackageName();
+    method @Deprecated public int getUid();
   }
 
-  public abstract static class MediaSession.SessionCallback {
-    ctor public MediaSession.SessionCallback();
-    method public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
-    method public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
-    method public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
-    method public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
-    method public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
-    method public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
-    method public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+  @Deprecated public abstract static class MediaSession.SessionCallback {
+    ctor @Deprecated public MediaSession.SessionCallback();
+    method @Deprecated public int onCommandRequest(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup? onConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public androidx.media2.common.MediaItem? onCreateMediaItem(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String);
+    method @Deprecated public androidx.media2.session.SessionResult onCustomCommand(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, androidx.media2.session.SessionCommand, android.os.Bundle?);
+    method @Deprecated public void onDisconnected(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onFastForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public void onPostConnect(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onRewind(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onSetMediaUri(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, android.net.Uri, android.os.Bundle?);
+    method @Deprecated public int onSetRating(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo, String, androidx.media2.common.Rating);
+    method @Deprecated public int onSkipBackward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public int onSkipForward(androidx.media2.session.MediaSession, androidx.media2.session.MediaSession.ControllerInfo);
   }
 
-  public final class MediaSessionManager {
-    method public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
-    method public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
+  @Deprecated public final class MediaSessionManager {
+    method @Deprecated public static androidx.media2.session.MediaSessionManager getInstance(android.content.Context);
+    method @Deprecated public java.util.Set<androidx.media2.session.SessionToken!> getSessionServiceTokens();
   }
 
-  public abstract class MediaSessionService extends android.app.Service {
-    ctor public MediaSessionService();
-    method public final void addSession(androidx.media2.session.MediaSession);
-    method public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
-    method @CallSuper public android.os.IBinder? onBind(android.content.Intent);
-    method public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
-    method public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
-    method public final void removeSession(androidx.media2.session.MediaSession);
-    field public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
+  @Deprecated public abstract class MediaSessionService extends android.app.Service {
+    ctor @Deprecated public MediaSessionService();
+    method @Deprecated public final void addSession(androidx.media2.session.MediaSession);
+    method @Deprecated public final java.util.List<androidx.media2.session.MediaSession!> getSessions();
+    method @Deprecated @CallSuper public android.os.IBinder? onBind(android.content.Intent);
+    method @Deprecated public abstract androidx.media2.session.MediaSession? onGetSession(androidx.media2.session.MediaSession.ControllerInfo);
+    method @Deprecated public androidx.media2.session.MediaSessionService.MediaNotification? onUpdateNotification(androidx.media2.session.MediaSession);
+    method @Deprecated public final void removeSession(androidx.media2.session.MediaSession);
+    field @Deprecated public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaSessionService";
   }
 
-  public static class MediaSessionService.MediaNotification {
-    ctor public MediaSessionService.MediaNotification(int, android.app.Notification);
-    method public android.app.Notification getNotification();
-    method public int getNotificationId();
+  @Deprecated public static class MediaSessionService.MediaNotification {
+    ctor @Deprecated public MediaSessionService.MediaNotification(int, android.app.Notification);
+    method @Deprecated public android.app.Notification getNotification();
+    method @Deprecated public int getNotificationId();
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class PercentageRating implements androidx.media2.common.Rating {
-    ctor public PercentageRating();
-    ctor public PercentageRating(float);
-    method public float getPercentRating();
-    method public boolean isRated();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class PercentageRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public PercentageRating();
+    ctor @Deprecated public PercentageRating(float);
+    method @Deprecated public float getPercentRating();
+    method @Deprecated public boolean isRated();
   }
 
-  public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
-    ctor public RemoteSessionPlayer();
-    method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
-    method public abstract int getMaxVolume();
-    method public abstract int getVolume();
-    method public abstract int getVolumeControlType();
-    method public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
-    field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
-    field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
-    field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+  @Deprecated public abstract class RemoteSessionPlayer extends androidx.media2.common.SessionPlayer {
+    ctor @Deprecated public RemoteSessionPlayer();
+    method @Deprecated public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> adjustVolume(int);
+    method @Deprecated public abstract int getMaxVolume();
+    method @Deprecated public abstract int getVolume();
+    method @Deprecated public abstract int getVolumeControlType();
+    method @Deprecated public abstract java.util.concurrent.Future<androidx.media2.common.SessionPlayer.PlayerResult!> setVolume(int);
+    field @Deprecated public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+    field @Deprecated public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+    field @Deprecated public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
   }
 
-  public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
-    ctor public RemoteSessionPlayer.Callback();
-    method public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
+  @Deprecated public static class RemoteSessionPlayer.Callback extends androidx.media2.common.SessionPlayer.PlayerCallback {
+    ctor @Deprecated public RemoteSessionPlayer.Callback();
+    method @Deprecated public void onVolumeChanged(androidx.media2.session.RemoteSessionPlayer, int);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionCommand(int);
-    ctor public SessionCommand(String, android.os.Bundle?);
-    method public int getCommandCode();
-    method public String? getCustomAction();
-    method public android.os.Bundle? getCustomExtras();
-    field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
-    field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
-    field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
-    field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
-    field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
-    field public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
-    field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
-    field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
-    field public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
-    field public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
-    field public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
-    field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
-    field public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
-    field public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
-    field public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
-    field public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
-    field public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
-    field public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
-    field public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
-    field public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
-    field public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
-    field public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
-    field public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
-    field public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
-    field public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
-    field public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
-    field public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
-    field public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
-    field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
-    field public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
-    field public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
-    field public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
-    field public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
-    field public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
-    field public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
-    field public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
-    field public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
-    field public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
-    field public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
-    field public static final int COMMAND_VERSION_1 = 1; // 0x1
-    field public static final int COMMAND_VERSION_2 = 2; // 0x2
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class SessionCommand implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionCommand(int);
+    ctor @Deprecated public SessionCommand(String, android.os.Bundle?);
+    method @Deprecated public int getCommandCode();
+    method @Deprecated public String? getCustomAction();
+    method @Deprecated public android.os.Bundle? getCustomExtras();
+    field @Deprecated public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351
+    field @Deprecated public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM = 10013; // 0x271d
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_DESELECT_TRACK = 11002; // 0x2afa
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_GET_CURRENT_MEDIA_ITEM = 10016; // 0x2720
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST = 10005; // 0x2715
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_GET_PLAYLIST_METADATA = 10012; // 0x271c
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_MOVE_PLAYLIST_ITEM = 10019; // 0x2723
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_PAUSE = 10001; // 0x2711
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_PLAY = 10000; // 0x2710
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_PREPARE = 10002; // 0x2712
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM = 10014; // 0x271e
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM = 10015; // 0x271f
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SEEK_TO = 10003; // 0x2713
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SELECT_TRACK = 11001; // 0x2af9
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_MEDIA_ITEM = 10018; // 0x2722
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_PLAYLIST = 10006; // 0x2716
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_REPEAT_MODE = 10011; // 0x271b
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_SHUFFLE_MODE = 10010; // 0x271a
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_SPEED = 10004; // 0x2714
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SET_SURFACE = 11000; // 0x2af8
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM = 10009; // 0x2719
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SKIP_TO_PLAYLIST_ITEM = 10007; // 0x2717
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM = 10008; // 0x2718
+    field @Deprecated public static final int COMMAND_CODE_PLAYER_UPDATE_LIST_METADATA = 10017; // 0x2721
+    field @Deprecated public static final int COMMAND_CODE_SESSION_FAST_FORWARD = 40000; // 0x9c40
+    field @Deprecated public static final int COMMAND_CODE_SESSION_REWIND = 40001; // 0x9c41
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; // 0x9c4b
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SKIP_BACKWARD = 40003; // 0x9c43
+    field @Deprecated public static final int COMMAND_CODE_SESSION_SKIP_FORWARD = 40002; // 0x9c42
+    field @Deprecated public static final int COMMAND_CODE_VOLUME_ADJUST_VOLUME = 30001; // 0x7531
+    field @Deprecated public static final int COMMAND_CODE_VOLUME_SET_VOLUME = 30000; // 0x7530
+    field @Deprecated public static final int COMMAND_VERSION_1 = 1; // 0x1
+    field @Deprecated public static final int COMMAND_VERSION_2 = 2; // 0x2
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionCommandGroup();
-    ctor public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
-    method public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
-    method public boolean hasCommand(androidx.media2.session.SessionCommand);
-    method public boolean hasCommand(int);
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class SessionCommandGroup implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionCommandGroup();
+    ctor @Deprecated public SessionCommandGroup(java.util.Collection<androidx.media2.session.SessionCommand!>?);
+    method @Deprecated public java.util.Set<androidx.media2.session.SessionCommand!> getCommands();
+    method @Deprecated public boolean hasCommand(androidx.media2.session.SessionCommand);
+    method @Deprecated public boolean hasCommand(int);
   }
 
-  public static final class SessionCommandGroup.Builder {
-    ctor public SessionCommandGroup.Builder();
-    ctor public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
-    method public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
-    method public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
-    method public androidx.media2.session.SessionCommandGroup build();
-    method public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
+  @Deprecated public static final class SessionCommandGroup.Builder {
+    ctor @Deprecated public SessionCommandGroup.Builder();
+    ctor @Deprecated public SessionCommandGroup.Builder(androidx.media2.session.SessionCommandGroup);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup.Builder addAllPredefinedCommands(int);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup.Builder addCommand(androidx.media2.session.SessionCommand);
+    method @Deprecated public androidx.media2.session.SessionCommandGroup build();
+    method @Deprecated public androidx.media2.session.SessionCommandGroup.Builder removeCommand(androidx.media2.session.SessionCommand);
   }
 
-  @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class SessionResult extends androidx.versionedparcelable.CustomVersionedParcelable {
-    ctor public SessionResult(int, android.os.Bundle?);
-    method public long getCompletionTime();
-    method public android.os.Bundle? getCustomCommandResult();
-    method public androidx.media2.common.MediaItem? getMediaItem();
-    method public int getResultCode();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize(isCustom=true) public class SessionResult extends androidx.versionedparcelable.CustomVersionedParcelable {
+    ctor @Deprecated public SessionResult(int, android.os.Bundle?);
+    method @Deprecated public long getCompletionTime();
+    method @Deprecated public android.os.Bundle? getCustomCommandResult();
+    method @Deprecated public androidx.media2.common.MediaItem? getMediaItem();
+    method @Deprecated public int getResultCode();
     field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd
     field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe
     field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb
@@ -415,34 +415,34 @@
     field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95
     field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff
     field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
-    field public static final int RESULT_SUCCESS = 0; // 0x0
+    field @Deprecated public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
-    ctor public SessionToken(android.content.Context, android.content.ComponentName);
-    method public android.os.Bundle getExtras();
-    method public String getPackageName();
-    method public String? getServiceName();
-    method public int getType();
-    method public int getUid();
-    field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
-    field public static final int TYPE_SESSION = 0; // 0x0
-    field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class SessionToken implements androidx.versionedparcelable.VersionedParcelable {
+    ctor @Deprecated public SessionToken(android.content.Context, android.content.ComponentName);
+    method @Deprecated public android.os.Bundle getExtras();
+    method @Deprecated public String getPackageName();
+    method @Deprecated public String? getServiceName();
+    method @Deprecated public int getType();
+    method @Deprecated public int getUid();
+    field @Deprecated public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
+    field @Deprecated public static final int TYPE_SESSION = 0; // 0x0
+    field @Deprecated public static final int TYPE_SESSION_SERVICE = 1; // 0x1
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class StarRating implements androidx.media2.common.Rating {
-    ctor public StarRating(@IntRange(from=1) int);
-    ctor public StarRating(@IntRange(from=1) int, float);
-    method public int getMaxStars();
-    method public float getStarRating();
-    method public boolean isRated();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class StarRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public StarRating(@IntRange(from=1) int);
+    ctor @Deprecated public StarRating(@IntRange(from=1) int, float);
+    method @Deprecated public int getMaxStars();
+    method @Deprecated public float getStarRating();
+    method @Deprecated public boolean isRated();
   }
 
-  @androidx.versionedparcelable.VersionedParcelize public final class ThumbRating implements androidx.media2.common.Rating {
-    ctor public ThumbRating();
-    ctor public ThumbRating(boolean);
-    method public boolean isRated();
-    method public boolean isThumbUp();
+  @Deprecated @androidx.versionedparcelable.VersionedParcelize public final class ThumbRating implements androidx.media2.common.Rating {
+    ctor @Deprecated public ThumbRating();
+    ctor @Deprecated public ThumbRating(boolean);
+    method @Deprecated public boolean isRated();
+    method @Deprecated public boolean isThumbUp();
   }
 
 }
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/HeartRating.java b/media2/media2-session/src/main/java/androidx/media2/session/HeartRating.java
index 68cdeb7..5a785d6 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/HeartRating.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/HeartRating.java
@@ -22,9 +22,13 @@
 import androidx.versionedparcelable.VersionedParcelize;
 
 /**
- * A class for rating with a single degree of rating, "heart" vs "no heart".
- * This can be used to indicate the content referred to is a favorite (or not).
+ * A class for rating with a single degree of rating, "heart" vs "no heart". This can be used to
+ * indicate the content referred to is a favorite (or not).
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class HeartRating implements Rating {
     @ParcelField(1)
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/LibraryResult.java b/media2/media2-session/src/main/java/androidx/media2/session/LibraryResult.java
index 0f09e4c..6fdd26a 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/LibraryResult.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/LibraryResult.java
@@ -38,9 +38,13 @@
 import java.util.List;
 
 /**
- * Result class to be used with {@link ListenableFuture} for asynchronous calls between
- * {@link MediaLibraryService.MediaLibrarySession} and {@link MediaBrowser}.
+ * Result class to be used with {@link ListenableFuture} for asynchronous calls between {@link
+ * MediaLibraryService.MediaLibrarySession} and {@link MediaBrowser}.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize(isCustom = true)
 public class LibraryResult extends CustomVersionedParcelable implements RemoteResult {
     /**
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaBrowser.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaBrowser.java
index dd0b9a3..410b736 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaBrowser.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaBrowser.java
@@ -33,14 +33,22 @@
 
 /**
  * Browses media content offered by a {@link MediaLibraryService}.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class MediaBrowser extends MediaController {
     static final String TAG = "MediaBrowser";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     /**
      * Callback to listen events from {@link MediaLibraryService}.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static class BrowserCallback extends MediaController.ControllerCallback {
         /**
          * Called when there's change in the parent's children after you've subscribed to the parent
@@ -294,17 +302,20 @@
 
     /**
      * Builder for {@link MediaBrowser}.
-     * <p>
-     * To set the token of the session for the controller to connect to, one of the
-     * {@link #setSessionToken(SessionToken)} or
-     * {@link #setSessionCompatToken(MediaSessionCompat.Token)} should be called.
-     * Otherwise, the {@link #build()} will throw an {@link IllegalArgumentException}.
-     * <p>
-     * Any incoming event from the {@link MediaSession} will be handled on the callback
-     * executor.
+     *
+     * <p>To set the token of the session for the controller to connect to, one of the {@link
+     * #setSessionToken(SessionToken)} or {@link #setSessionCompatToken(MediaSessionCompat.Token)}
+     * should be called. Otherwise, the {@link #build()} will throw an {@link
+     * IllegalArgumentException}.
+     *
+     * <p>Any incoming event from the {@link MediaSession} will be handled on the callback executor.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
-    public static final class Builder extends
-            BuilderBase<MediaBrowser, MediaBrowser.Builder, BrowserCallback> {
+    @Deprecated
+    public static final class Builder
+            extends BuilderBase<MediaBrowser, MediaBrowser.Builder, BrowserCallback> {
         public Builder(@NonNull Context context) {
             super(context);
         }
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaConstants.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaConstants.java
index 5310734..4e1be15 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaConstants.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaConstants.java
@@ -20,7 +20,11 @@
 
 /**
  * Media constants for sharing constants between media provider and consumer apps
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class MediaConstants {
     /**
      * A {@link android.net.Uri} scheme used in a media Uri.
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaController.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaController.java
index 044e1e0..a7eddd0 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaController.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaController.java
@@ -74,51 +74,56 @@
 import java.util.concurrent.Executors;
 
 /**
- * Allows an app to interact with an active {@link MediaSession} or a
- * {@link MediaSessionService} which would provide {@link MediaSession}. Media buttons and other
- * commands can be sent to the session.
- * <p>
- * MediaController objects are thread-safe.
- * <p>
- * Topics covered here:
+ * Allows an app to interact with an active {@link MediaSession} or a {@link MediaSessionService}
+ * which would provide {@link MediaSession}. Media buttons and other commands can be sent to the
+ * session.
+ *
+ * <p>MediaController objects are thread-safe.
+ *
+ * <p>Topics covered here:
+ *
  * <ol>
- * <li><a href="#ControllerLifeCycle">Controller Lifecycle</a>
- * <li><a href="#MediaSessionInTheSameProcess">Controlling the {@link MediaSession} in the same
- * process</a>
- * <li><a href="#PackageVisibilityFilter">Package Visibility Filter</a>
+ *   <li><a href="#ControllerLifeCycle">Controller Lifecycle</a>
+ *   <li><a href="#MediaSessionInTheSameProcess">Controlling the {@link MediaSession} in the same
+ *       process</a>
+ *   <li><a href="#PackageVisibilityFilter">Package Visibility Filter</a>
  * </ol>
+ *
  * <h3 id="ControllerLifeCycle">Controller Lifecycle</h3>
- * <p>
- * When a controller is created with the {@link SessionToken} for a {@link MediaSession} (i.e.
+ *
+ * <p>When a controller is created with the {@link SessionToken} for a {@link MediaSession} (i.e.
  * session token type is {@link SessionToken#TYPE_SESSION}), the controller will connect to the
  * specific session.
- * <p>
- * When a controller is created with the {@link SessionToken} for a {@link MediaSessionService}
- * (i.e. session token type is {@link SessionToken#TYPE_SESSION_SERVICE} or
- * {@link SessionToken#TYPE_LIBRARY_SERVICE}), the controller binds to the service for connecting
- * to a {@link MediaSession} in it. {@link MediaSessionService} will provide a session to connect.
- * <p>
- * When a controller connects to a session,
- * {@link MediaSession.SessionCallback#onConnect(MediaSession, MediaSession.ControllerInfo)}
- * will be called to either accept or reject the connection. Wait
- * {@link ControllerCallback#onConnected(MediaController, SessionCommandGroup)} or
- * {@link ControllerCallback#onDisconnected(MediaController)} for the result.
- * <p>
- * When the connected session is closed, the controller will receive
- * {@link ControllerCallback#onDisconnected(MediaController)}.
- * <p>
- * When you're done, use {@link #close()} to clean up resources. This also helps session service
+ *
+ * <p>When a controller is created with the {@link SessionToken} for a {@link MediaSessionService}
+ * (i.e. session token type is {@link SessionToken#TYPE_SESSION_SERVICE} or {@link
+ * SessionToken#TYPE_LIBRARY_SERVICE}), the controller binds to the service for connecting to a
+ * {@link MediaSession} in it. {@link MediaSessionService} will provide a session to connect.
+ *
+ * <p>When a controller connects to a session, {@link
+ * MediaSession.SessionCallback#onConnect(MediaSession, MediaSession.ControllerInfo)} will be called
+ * to either accept or reject the connection. Wait {@link
+ * ControllerCallback#onConnected(MediaController, SessionCommandGroup)} or {@link
+ * ControllerCallback#onDisconnected(MediaController)} for the result.
+ *
+ * <p>When the connected session is closed, the controller will receive {@link
+ * ControllerCallback#onDisconnected(MediaController)}.
+ *
+ * <p>When you're done, use {@link #close()} to clean up resources. This also helps session service
  * to be destroyed when there's no controller associated with it.
- * <p>
- * <a name="MediaSessionInTheSameProcess"></a>
+ *
+ * <p><a name="MediaSessionInTheSameProcess"></a>
+ *
  * <h3>Controlling the MediaSession in the same process</h3>
+ *
  * When you control the {@link MediaSession} and its {@link SessionPlayer}, it's recommended to use
- * them directly rather than creating {@link MediaController}. However, if you need to use
- * {@link MediaController} in the same process, be careful not to block session callback executor's
- * thread. Here's an example code that would never return due to the thread issue.
+ * them directly rather than creating {@link MediaController}. However, if you need to use {@link
+ * MediaController} in the same process, be careful not to block session callback executor's thread.
+ * Here's an example code that would never return due to the thread issue.
+ *
  * <p>
- * <pre>
- * {@code
+ *
+ * <pre>{@code
  * // Code runs on the main thread.
  * MediaSession session = new MediaSession.Builder(context, player)
  *    .setSessionCallback(sessionCallback, Context.getMainExecutor(context)).build();
@@ -128,25 +133,28 @@
  *    .build();
  *
  * // This will hang and never return.
- * controller.play().get();}</pre>
+ * controller.play().get();
+ * }</pre>
  *
- * When a session gets a command from a controller, the session's
- * {@link MediaSession.SessionCallback#onCommandRequest} would be executed on the session's
- * callback executor to decide whether to ignore or handle the incoming command. To do so, the
- * session's callback executor shouldn't be blocked to handle the incoming calls. However, if you
- * call {@link ListenableFuture#get} on the thread for the session callback executor, then your
- * call wouldn't be executed and never return.
- * <p>
- * To avoid such issue, don't block the session callback executor's thread. Creating a dedicated
- * thread for the session callback executor would be helpful. See
- * {@link Executors#newSingleThreadExecutor} for creating a new thread.
+ * When a session gets a command from a controller, the session's {@link
+ * MediaSession.SessionCallback#onCommandRequest} would be executed on the session's callback
+ * executor to decide whether to ignore or handle the incoming command. To do so, the session's
+ * callback executor shouldn't be blocked to handle the incoming calls. However, if you call {@link
+ * ListenableFuture#get} on the thread for the session callback executor, then your call wouldn't be
+ * executed and never return.
+ *
+ * <p>To avoid such issue, don't block the session callback executor's thread. Creating a dedicated
+ * thread for the session callback executor would be helpful. See {@link
+ * Executors#newSingleThreadExecutor} for creating a new thread.
+ *
  * <h3 id="PackageVisibilityFilter">Package Visibility Filter</h3>
- * <p>
- * The app targeting API level 30 or higher must include a {@code <queries>} element in their
+ *
+ * <p>The app targeting API level 30 or higher must include a {@code <queries>} element in their
  * manifest to connect to a service component of another app like {@link MediaSessionService},
  * {@link MediaLibraryService}, or {@link androidx.media.MediaBrowserServiceCompat}). See the
  * following example and <a href="{@docRoot}training/package-visibility">this guide</a> for more
  * information.
+ *
  * <pre>{@code
  * <!-- As intent actions -->
  * <intent>
@@ -164,7 +172,10 @@
  *
  * @see MediaSession
  * @see MediaSessionService
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class MediaController implements Closeable {
     private static final String TAG = "MediaController";
 
@@ -1613,20 +1624,22 @@
         MediaBrowserCompat getBrowserCompat();
     }
 
-
     /**
      * Builder for {@link MediaController}.
-     * <p>
-     * To set the token of the session for the controller to connect to, one of the
-     * {@link #setSessionToken(SessionToken)} or
-     * {@link #setSessionCompatToken(MediaSessionCompat.Token)} should be called.
-     * Otherwise, the {@link #build()} will throw an {@link IllegalArgumentException}.
-     * <p>
-     * Any incoming event from the {@link MediaSession} will be handled on the callback
-     * executor.
+     *
+     * <p>To set the token of the session for the controller to connect to, one of the {@link
+     * #setSessionToken(SessionToken)} or {@link #setSessionCompatToken(MediaSessionCompat.Token)}
+     * should be called. Otherwise, the {@link #build()} will throw an {@link
+     * IllegalArgumentException}.
+     *
+     * <p>Any incoming event from the {@link MediaSession} will be handled on the callback executor.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
-    public static final class Builder extends BuilderBase<MediaController, Builder,
-            ControllerCallback> {
+    @Deprecated
+    public static final class Builder
+            extends BuilderBase<MediaController, Builder, ControllerCallback> {
         public Builder(@NonNull Context context) {
             super(context);
         }
@@ -1840,9 +1853,13 @@
     }
 
     /**
-     * Interface for listening to change in activeness of the {@link MediaSession}.  It's
-     * active if and only if it has set a player.
+     * Interface for listening to change in activeness of the {@link MediaSession}. It's active if
+     * and only if it has set a player.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public abstract static class ControllerCallback {
         /**
          * Called when the controller is successfully connected to the session. The controller
@@ -2135,8 +2152,12 @@
 
     /**
      * Holds information about the way volume is handled for this session.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
     // The same as MediaController.PlaybackInfo
+    @Deprecated
     @VersionedParcelize
     public static final class PlaybackInfo implements VersionedParcelable {
         @ParcelField(1)
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaLibraryService.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaLibraryService.java
index 5566fb6..b063bcd 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaLibraryService.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaLibraryService.java
@@ -45,26 +45,34 @@
 import java.util.concurrent.Executor;
 
 /**
- * Base class for media library services, which is the service containing
- * {@link MediaLibrarySession}.
- * <p>
- * Media library services enable applications to browse media content provided by an application
- * and ask the application to start playing it. They may also be used to control content that
- * is already playing by way of a {@link MediaSession}.
- * <p>
- * When extending this class, also add the following to your {@code AndroidManifest.xml}.
+ * Base class for media library services, which is the service containing {@link
+ * MediaLibrarySession}.
+ *
+ * <p>Media library services enable applications to browse media content provided by an application
+ * and ask the application to start playing it. They may also be used to control content that is
+ * already playing by way of a {@link MediaSession}.
+ *
+ * <p>When extending this class, also add the following to your {@code AndroidManifest.xml}.
+ *
  * <pre>
  * &lt;service android:name="component_name_of_your_implementation" &gt;
  *   &lt;intent-filter&gt;
  *     &lt;action android:name="androidx.media2.session.MediaLibraryService" /&gt;
  *   &lt;/intent-filter&gt;
  * &lt;/service&gt;</pre>
- * <p>
- * You may also declare <pre>android.media.browse.MediaBrowserService</pre> for compatibility with
- * {@link android.support.v4.media.MediaBrowserCompat}. This service can handle it automatically.
+ *
+ * <p>You may also declare
+ *
+ * <pre>android.media.browse.MediaBrowserService</pre>
+ *
+ * for compatibility with {@link android.support.v4.media.MediaBrowserCompat}. This service can
+ * handle it automatically.
  *
  * @see MediaSessionService
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public abstract class MediaLibraryService extends MediaSessionService {
     /**
      * The {@link Intent} that must be declared as handled by the service.
@@ -72,13 +80,14 @@
     public static final String SERVICE_INTERFACE = "androidx.media2.session.MediaLibraryService";
 
     /**
-     * Session for the {@link MediaLibraryService}. Build this object with
-     * {@link Builder} and return in {@link MediaSessionService#onGetSession(ControllerInfo)}.
+     * Session for the {@link MediaLibraryService}. Build this object with {@link Builder} and
+     * return in {@link MediaSessionService#onGetSession(ControllerInfo)}.
      *
      * <h3 id="BackwardCompatibility">Backward compatibility with legacy media browser APIs</h3>
-     * Media library session supports connection from both {@link MediaBrowser} and
-     * {@link android.support.v4.media.MediaBrowserCompat}, but {@link ControllerInfo} may not be
-     * precise. Here are current limitations with details.
+     *
+     * Media library session supports connection from both {@link MediaBrowser} and {@link
+     * android.support.v4.media.MediaBrowserCompat}, but {@link ControllerInfo} may not be precise.
+     * Here are current limitations with details.
      *
      * <table>
      * <tr><th>SDK version</th>
@@ -99,18 +108,25 @@
      *     <td>Actual package name via {@link Context#getPackageName()}</td>
      *     <td>Actual UID</td></tr>
      * </table>
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class MediaLibrarySession extends MediaSession {
         private final boolean mThrowsWhenInvalidReturn;
 
         /**
          * Callback for the {@link MediaLibrarySession}.
-         * <p>
-         * When you return {@link LibraryResult} with media items,
-         * items must have valid {@link MediaMetadata#METADATA_KEY_MEDIA_ID} and
-         * specify {@link MediaMetadata#METADATA_KEY_BROWSABLE} and
-         * {@link MediaMetadata#METADATA_KEY_PLAYABLE}.
+         *
+         * <p>When you return {@link LibraryResult} with media items, items must have valid {@link
+         * MediaMetadata#METADATA_KEY_MEDIA_ID} and specify {@link
+         * MediaMetadata#METADATA_KEY_BROWSABLE} and {@link MediaMetadata#METADATA_KEY_PLAYABLE}.
+         *
+         * @deprecated androidx.media2 is deprecated. Please migrate to <a
+         *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a> .
          */
+        @Deprecated
         public static class MediaLibrarySessionCallback extends MediaSession.SessionCallback {
             /**
              * Called to get the root information for browsing by a {@link MediaBrowser}.
@@ -289,17 +305,22 @@
 
         /**
          * Builder for {@link MediaLibrarySession}.
-         * <p>
-         * Any incoming event from the {@link MediaController} will be handled on the callback
+         *
+         * <p>Any incoming event from the {@link MediaController} will be handled on the callback
          * executor. If it's not set, {@link ContextCompat#getMainExecutor(Context)} will be used by
          * default.
+         *
+         * @deprecated androidx.media2 is deprecated. Please migrate to <a
+         *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a> .
          */
         // Override all methods just to show them with the type instead of generics in Javadoc.
         // This workarounds javadoc issue described in the MediaSession.BuilderBase.
         // Note: Don't override #setSessionCallback() because the callback can be set by the
         // constructor.
-        public static final class Builder extends MediaSession.BuilderBase<MediaLibrarySession,
-                Builder, MediaLibrarySessionCallback> {
+        @Deprecated
+        public static final class Builder
+                extends MediaSession.BuilderBase<
+                        MediaLibrarySession, Builder, MediaLibrarySessionCallback> {
             private boolean mThrowsWhenInvalidReturn = true;
 
             // Builder requires MediaLibraryService instead of Context just to ensure that the
@@ -511,14 +532,18 @@
 
     /**
      * Contains information that the library service needs to send to the client.
-     * <p>
-     * When the browser supplies {@link LibraryParams}, it's optional field when getting the media
-     * item(s). The library session is recommended to do the best effort to provide such result.
-     * It's not an error even when the library session didn't return such items.
-     * <p>
-     * The library params returned in the library session callback must include the information
+     *
+     * <p>When the browser supplies {@link LibraryParams}, it's optional field when getting the
+     * media item(s). The library session is recommended to do the best effort to provide such
+     * result. It's not an error even when the library session didn't return such items.
+     *
+     * <p>The library params returned in the library session callback must include the information
      * about the returned media item(s).
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     @VersionedParcelize
     public static final class LibraryParams implements VersionedParcelable {
         @ParcelField(1)
@@ -618,7 +643,11 @@
 
         /**
          * Builds a {@link LibraryParams}.
+         *
+         * @deprecated androidx.media2 is deprecated. Please migrate to <a
+         *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
          */
+        @Deprecated
         public static final class Builder {
             private boolean mRecent;
             private boolean mOffline;
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaSession.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaSession.java
index d425b40..14dbbc0 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaSession.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaSession.java
@@ -69,50 +69,54 @@
 /**
  * Allows a media app to expose its transport controls and playback information in a process to
  * other processes including the Android framework and other apps. Common use cases are as follows.
- * <ul>
- *     <li>Bluetooth/wired headset key events support</li>
- *     <li>Android Auto/Wearable support</li>
- *     <li>Separating UI process and playback process</li>
- * </ul>
- * <p>
- * A MediaSession should be created when an app wants to publish media playback information or
- * handle media keys. In general an app only needs one session for all playback, though multiple
- * sessions can be created to provide finer grain controls of media. See
- * <a href="#MultipleSessions">Supporting Multiple Sessions</a> for detail.
- * <p>
- * If you want to support background playback, {@link MediaSessionService} is preferred
- * instead. With it, your playback can be revived even after playback is finished. See
- * {@link MediaSessionService} for details.
- * <p>
- * Topics covered here:
- * <ol>
- * <li><a href="#SessionLifecycle">Session Lifecycle</a>
- * <li><a href="#Thread">Thread</a>
- * <li><a href="#KeyEvents">Media key events mapping</a>
- * <li><a href="#MultipleSessions">Supporting Multiple Sessions</a>
- * <li><a href="#CompatibilitySession">Backward compatibility with legacy session APIs</a>
- * <li><a href="#CompatibilityController">Backward compatibility with legacy controller APIs</a>
  *
+ * <ul>
+ *   <li>Bluetooth/wired headset key events support
+ *   <li>Android Auto/Wearable support
+ *   <li>Separating UI process and playback process
+ * </ul>
+ *
+ * <p>A MediaSession should be created when an app wants to publish media playback information or
+ * handle media keys. In general an app only needs one session for all playback, though multiple
+ * sessions can be created to provide finer grain controls of media. See <a
+ * href="#MultipleSessions">Supporting Multiple Sessions</a> for detail.
+ *
+ * <p>If you want to support background playback, {@link MediaSessionService} is preferred instead.
+ * With it, your playback can be revived even after playback is finished. See {@link
+ * MediaSessionService} for details.
+ *
+ * <p>Topics covered here:
+ *
+ * <ol>
+ *   <li><a href="#SessionLifecycle">Session Lifecycle</a>
+ *   <li><a href="#Thread">Thread</a>
+ *   <li><a href="#KeyEvents">Media key events mapping</a>
+ *   <li><a href="#MultipleSessions">Supporting Multiple Sessions</a>
+ *   <li><a href="#CompatibilitySession">Backward compatibility with legacy session APIs</a>
+ *   <li><a href="#CompatibilityController">Backward compatibility with legacy controller APIs</a>
  * </ol>
+ *
  * <h3 id="SessionLifecycle">Session Lifecycle</h3>
- * <p>
- * A session can be obtained by {@link Builder}. The owner of the session may pass its session token
- * to other processes to allow them to create a {@link MediaController} to interact with the
+ *
+ * <p>A session can be obtained by {@link Builder}. The owner of the session may pass its session
+ * token to other processes to allow them to create a {@link MediaController} to interact with the
  * session.
- * <p>
- * When a session receive transport control commands, the session sends the commands directly to
+ *
+ * <p>When a session receive transport control commands, the session sends the commands directly to
  * the underlying media player set by {@link Builder} or {@link #updatePlayer}.
- * <p>
- * When an app is finished performing playback it must call {@link #close()} to clean up the session
- * and notify any controllers. The app is responsible for closing the underlying player after
- * closing the session.
- * is closed.
+ *
+ * <p>When an app is finished performing playback it must call {@link #close()} to clean up the
+ * session and notify any controllers. The app is responsible for closing the underlying player
+ * after closing the session. is closed.
+ *
  * <h3 id="Thread">Thread</h3>
- * <p>
- * {@link MediaSession} objects are thread safe, but should be used on the thread on the looper.
+ *
+ * <p>{@link MediaSession} objects are thread safe, but should be used on the thread on the looper.
+ *
  * <h3 id="KeyEvents">Media key events mapping</h3>
- * <p>
- * Here's the table of per key event.
+ *
+ * <p>Here's the table of per key event.
+ *
  * <table>
  * <tr><th>Key code</th><th>{@link MediaSession} API</th></tr>
  * <tr><td>{@link KeyEvent#KEYCODE_MEDIA_PLAY}</td>
@@ -139,34 +143,43 @@
  *             <li>For a double tap, {@link SessionPlayer#skipToNextPlaylistItem()}</li></ul></td>
  *     </tr>
  * </table>
+ *
  * <h3 id="MultipleSessions">Supporting Multiple Sessions</h3>
+ *
  * Generally speaking, multiple sessions aren't necessary for most media apps. One exception is if
  * your app can play multiple media content at the same time, but only for the playback of
- * video-only media or remote playback, since
- * <a href="{@docRoot}guide/topics/media-apps/audio-focus.html">audio focus policy</a> recommends
- * not playing multiple audio content at the same time. Also keep in mind that multiple media
- * sessions would make Android Auto and Bluetooth device with display to show your apps multiple
- * times, because they list up media sessions, not media apps.
+ * video-only media or remote playback, since <a
+ * href="{@docRoot}guide/topics/media-apps/audio-focus.html">audio focus policy</a> recommends not
+ * playing multiple audio content at the same time. Also keep in mind that multiple media sessions
+ * would make Android Auto and Bluetooth device with display to show your apps multiple times,
+ * because they list up media sessions, not media apps.
+ *
  * <h3 id="CompatibilitySession">Backward compatibility with legacy session APIs</h3>
+ *
  * An active {@link MediaSessionCompat} is internally created with the MediaSession for the backward
- * compatibility. It's used to handle incoming connection and command from
- * {@link MediaControllerCompat}. And helps to utilize existing APIs that are built with legacy
- * media session APIs. Use {@link #getSessionCompatToken} for getting the token for the underlying
+ * compatibility. It's used to handle incoming connection and command from {@link
+ * MediaControllerCompat}. And helps to utilize existing APIs that are built with legacy media
+ * session APIs. Use {@link #getSessionCompatToken} for getting the token for the underlying
  * MediaSessionCompat.
+ *
  * <h3 id="CompatibilityController">Backward compatibility with legacy controller APIs</h3>
+ *
  * In addition to the {@link MediaController media2 controller} API, session also supports
- * connection from the legacy controller API -
- * {@link android.media.session.MediaController framework controller} and
- * {@link MediaControllerCompat AndroidX controller compat}.
- * However, {@link ControllerInfo} may not be precise for legacy controller.
- * See {@link ControllerInfo} for the details.
- * <p>
- * Unknown package name nor UID doesn't mean that you should disallow connection nor commands. For
- * SDK levels where such issue happen, session tokens could only be obtained by trusted apps (e.g.
- * Bluetooth, Auto, ...), so it may be better for you to allow them as you did with legacy session.
+ * connection from the legacy controller API - {@link android.media.session.MediaController
+ * framework controller} and {@link MediaControllerCompat AndroidX controller compat}. However,
+ * {@link ControllerInfo} may not be precise for legacy controller. See {@link ControllerInfo} for
+ * the details.
+ *
+ * <p>Unknown package name nor UID doesn't mean that you should disallow connection nor commands.
+ * For SDK levels where such issue happen, session tokens could only be obtained by trusted apps
+ * (e.g. Bluetooth, Auto, ...), so it may be better for you to allow them as you did with legacy
+ * session.
  *
  * @see MediaSessionService
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class MediaSession implements Closeable {
 
     // It's better to have private static lock instead of using MediaSession.class because the
@@ -467,10 +480,14 @@
 
     /**
      * Callback to be called for all incoming commands from {@link MediaController}s.
-     * <p>
-     * If it's not set, the session will accept all controllers and all incoming commands by
+     *
+     * <p>If it's not set, the session will accept all controllers and all incoming commands by
      * default.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public abstract static class SessionCallback {
         ForegroundServiceEventCallback mForegroundServiceEventCallback;
 
@@ -808,10 +825,15 @@
 
     /**
      * Builder for {@link MediaSession}.
-     * <p>
-     * Any incoming event from the {@link MediaController} will be handled on the callback executor.
-     * If it's not set, {@link ContextCompat#getMainExecutor(Context)} will be used by default.
+     *
+     * <p>Any incoming event from the {@link MediaController} will be handled on the callback
+     * executor. If it's not set, {@link ContextCompat#getMainExecutor(Context)} will be used by
+     * default.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder extends BuilderBase<MediaSession, Builder, SessionCallback> {
         public Builder(@NonNull Context context, @NonNull SessionPlayer player) {
             super(context, player);
@@ -858,7 +880,11 @@
 
     /**
      * Information of a controller.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class ControllerInfo {
         @SuppressWarnings("UnusedVariable")
         private final int mControllerVersion;
@@ -1003,9 +1029,13 @@
 
     /**
      * Button for a {@link SessionCommand} that will be shown by the controller.
-     * <p>
-     * It's up to the controller's decision to respect or ignore this customization request.
+     *
+     * <p>It's up to the controller's decision to respect or ignore this customization request.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     @VersionedParcelize
     public static final class CommandButton implements VersionedParcelable {
         @ParcelField(1)
@@ -1090,7 +1120,11 @@
 
         /**
          * Builder for {@link CommandButton}.
+         *
+         * @deprecated androidx.media2 is deprecated. Please migrate to <a
+         *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a> .
          */
+        @Deprecated
         public static final class Builder {
             private SessionCommand mCommand;
             private int mIconResId;
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionManager.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionManager.java
index d628d7b..0310d67 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionManager.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionManager.java
@@ -36,8 +36,8 @@
 import java.util.Set;
 
 /**
- * Provides support for interacting with media sessions that applications have published
- * in order to express their ongoing media playback state.
+ * Provides support for interacting with media sessions that applications have published in order to
+ * express their ongoing media playback state.
  *
  * @see MediaSessionCompat
  * @see MediaSession
@@ -46,7 +46,10 @@
  * @see MediaControllerCompat
  * @see MediaController
  * @see MediaBrowser
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public final class MediaSessionManager {
     static final String TAG = "MediaSessionManager";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionService.java b/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionService.java
index d8a459e..1984eae 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionService.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/MediaSessionService.java
@@ -32,88 +32,102 @@
 
 /**
  * Base class for media session services, which is the service containing {@link MediaSession}.
- * <p>
- * It's highly recommended for an app to use this if it wants to keep media playback in the
+ *
+ * <p>It's highly recommended for an app to use this if it wants to keep media playback in the
  * background.
- * <p>
- * Here are the benefits of using {@link MediaSessionService}.
+ *
+ * <p>Here are the benefits of using {@link MediaSessionService}.
+ *
  * <ul>
- * <li>Another app can know that your app supports {@link MediaSession} even when your app
- * isn't running.
- * <li>Another app can start playback of your app even when your app isn't running.
+ *   <li>Another app can know that your app supports {@link MediaSession} even when your app isn't
+ *       running.
+ *   <li>Another app can start playback of your app even when your app isn't running.
  * </ul>
+ *
  * For example, user's voice command can start playback of your app even when it's not running.
- * <p>
- * To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
+ *
+ * <p>To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
+ *
  * <pre>
  * &lt;service android:name="component_name_of_your_implementation" &gt;
  *   &lt;intent-filter&gt;
  *     &lt;action android:name="androidx.media2.session.MediaSessionService" /&gt;
  *   &lt;/intent-filter&gt;
  * &lt;/service&gt;</pre>
- * <p>
- * You may also declare <pre>android.media.browse.MediaBrowserService</pre> for compatibility with
- * {@link android.support.v4.media.MediaBrowserCompat}. This service can handle it automatically.
- * <p>
- * It's recommended for an app to have a single {@link MediaSessionService} declared in the
+ *
+ * <p>You may also declare
+ *
+ * <pre>android.media.browse.MediaBrowserService</pre>
+ *
+ * for compatibility with {@link android.support.v4.media.MediaBrowserCompat}. This service can
+ * handle it automatically.
+ *
+ * <p>It's recommended for an app to have a single {@link MediaSessionService} declared in the
  * manifest. Otherwise, your app might be shown twice in the list of the Auto/Wearable, or another
- * app fails to pick the right session service when it wants to start the playback of this app.
- * If you want to provide multiple sessions here, take a look at
- * <a href="#MultipleSessions">Supporting Multiple Sessions</a>.
- * <p>
- * Topics covered here:
+ * app fails to pick the right session service when it wants to start the playback of this app. If
+ * you want to provide multiple sessions here, take a look at <a href="#MultipleSessions">Supporting
+ * Multiple Sessions</a>.
+ *
+ * <p>Topics covered here:
+ *
  * <ol>
- * <li><a href="#ServiceLifecycle">Service Lifecycle</a>
- * <li><a href="#Permissions">Permissions</a>
- * <li><a href="#MultipleSessions">Supporting Multiple Sessions</a>
+ *   <li><a href="#ServiceLifecycle">Service Lifecycle</a>
+ *   <li><a href="#Permissions">Permissions</a>
+ *   <li><a href="#MultipleSessions">Supporting Multiple Sessions</a>
  * </ol>
+ *
  * <div>
+ *
  * <h3 id="ServiceLifecycle">Service Lifecycle</h3>
- * <p>
- * Session service is a bound service. When a {@link MediaController} is created for the
- * session service, the controller binds to the session service.
- * {@link #onGetSession(ControllerInfo)} would be called inside of the {@link #onBind(Intent)}.
- * <p>
- * After the binding, session's
- * {@link MediaSession.SessionCallback#onConnect(MediaSession, MediaSession.ControllerInfo)}
- * will be called to accept or reject connection request from a controller. If the connection is
- * rejected, the controller will unbind. If it's accepted, the controller will be available to use
- * and keep binding.
- * <p>
- * When playback is started for this session service, {@link #onUpdateNotification(MediaSession)}
+ *
+ * <p>Session service is a bound service. When a {@link MediaController} is created for the session
+ * service, the controller binds to the session service. {@link #onGetSession(ControllerInfo)} would
+ * be called inside of the {@link #onBind(Intent)}.
+ *
+ * <p>After the binding, session's {@link MediaSession.SessionCallback#onConnect(MediaSession,
+ * MediaSession.ControllerInfo)} will be called to accept or reject connection request from a
+ * controller. If the connection is rejected, the controller will unbind. If it's accepted, the
+ * controller will be available to use and keep binding.
+ *
+ * <p>When playback is started for this session service, {@link #onUpdateNotification(MediaSession)}
  * is called for the playback's session and service would become a foreground service. It's needed
  * to keep playback after the controller is destroyed. The session service becomes background
- * service when all playbacks are stopped. Apps targeting API
- * {@link android.os.Build.VERSION_CODES#P} or later must request the permission
- * {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to make the service foreground.
- * <p>
- * The service is destroyed when the all sessions are closed, or no media controller is binding to
- * the session while the service is not running as a foreground service.
+ * service when all playbacks are stopped. Apps targeting API {@link
+ * android.os.Build.VERSION_CODES#P} or later must request the permission {@link
+ * android.Manifest.permission#FOREGROUND_SERVICE} in order to make the service foreground.
+ *
+ * <p>The service is destroyed when the all sessions are closed, or no media controller is binding
+ * to the session while the service is not running as a foreground service.
+ *
  * <h3 id="Permissions">Permissions</h3>
- * <p>
- * Any app can bind to the session service with controller, but the controller can be used only if
- * the session service accepted the connection request through
- * {@link MediaSession.SessionCallback#onConnect(MediaSession, MediaSession.ControllerInfo)}.
+ *
+ * <p>Any app can bind to the session service with controller, but the controller can be used only
+ * if the session service accepted the connection request through {@link
+ * MediaSession.SessionCallback#onConnect(MediaSession, MediaSession.ControllerInfo)}.
+ *
  * <h3 id="MultipleSessions">Supporting Multiple Sessions</h3>
+ *
  * Generally speaking, multiple sessions aren't necessary for most media apps. One exception is if
  * your app can play multiple media content at the same time, but only for the playback of
- * video-only media or remote playback, since
- * <a href="{@docRoot}guide/topics/media-apps/audio-focus.html">audio focus policy</a> recommends
- * not playing multiple audio content at the same time. Also keep in mind that multiple media
- * sessions would make Android Auto and Bluetooth device with display to show your apps multiple
- * times, because they list up media sessions, not media apps.
- * <p>
- * However, if you're capable of handling multiple playback and want to keep their sessions while
- * the app is in the background, create multiple sessions and add to this service with
- * {@link #addSession(MediaSession)}.
- * <p>
- * Note that {@link MediaController} can be created with {@link SessionToken} for
- * connecting any session in this service. In that case, {@link #onGetSession(ControllerInfo)} will
- * be called to know which session to handle incoming connection request. Pick the best session
- * among added sessions, or create new one and return from the
- * {@link #onGetSession(ControllerInfo)}.
- * </div>
+ * video-only media or remote playback, since <a
+ * href="{@docRoot}guide/topics/media-apps/audio-focus.html">audio focus policy</a> recommends not
+ * playing multiple audio content at the same time. Also keep in mind that multiple media sessions
+ * would make Android Auto and Bluetooth device with display to show your apps multiple times,
+ * because they list up media sessions, not media apps.
+ *
+ * <p>However, if you're capable of handling multiple playback and want to keep their sessions while
+ * the app is in the background, create multiple sessions and add to this service with {@link
+ * #addSession(MediaSession)}.
+ *
+ * <p>Note that {@link MediaController} can be created with {@link SessionToken} for connecting any
+ * session in this service. In that case, {@link #onGetSession(ControllerInfo)} will be called to
+ * know which session to handle incoming connection request. Pick the best session among added
+ * sessions, or create new one and return from the {@link #onGetSession(ControllerInfo)}. </div>
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public abstract class MediaSessionService extends Service {
     /**
      * The {@link Intent} that must be declared as handled by the service.
@@ -291,10 +305,14 @@
     }
 
     /**
-     * Returned by {@link #onUpdateNotification(MediaSession)} for making session service
-     * foreground service to keep playback running in the background. It's highly recommended to
-     * show media style notification here.
+     * Returned by {@link #onUpdateNotification(MediaSession)} for making session service foreground
+     * service to keep playback running in the background. It's highly recommended to show media
+     * style notification here.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static class MediaNotification {
         private final int mNotificationId;
         private final Notification mNotification;
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/PercentageRating.java b/media2/media2-session/src/main/java/androidx/media2/session/PercentageRating.java
index 33c2655..6a3fb90 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/PercentageRating.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/PercentageRating.java
@@ -23,7 +23,11 @@
 
 /**
  * A class for rating expressed as a percentage.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class PercentageRating implements Rating {
     private static final float RATING_NOT_RATED = -1.0f;
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/RemoteResult.java b/media2/media2-session/src/main/java/androidx/media2/session/RemoteResult.java
index bf836e6..9d8f72c 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/RemoteResult.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/RemoteResult.java
@@ -19,9 +19,13 @@
 import androidx.media2.common.BaseResult;
 
 /**
- * Base interface for result classes in {@link MediaSession} and {@link MediaController} that may
- * be sent across the processes.
+ * Base interface for result classes in {@link MediaSession} and {@link MediaController} that may be
+ * sent across the processes.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 interface RemoteResult extends BaseResult {
     /**
      * Result code representing that the session and controller were disconnected.
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/RemoteSessionPlayer.java b/media2/media2-session/src/main/java/androidx/media2/session/RemoteSessionPlayer.java
index cf2a8ca..9542545 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/RemoteSessionPlayer.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/RemoteSessionPlayer.java
@@ -31,10 +31,14 @@
 /**
  * Base interface for all remote media players that want media session and playback happens on the
  * remote device through MediaRouter.
- * <p>
- * If you use this to the {@link MediaSession}, session would dispatch incoming volume change event
- * to the player instead of changing device stream volume.
+ *
+ * <p>If you use this to the {@link MediaSession}, session would dispatch incoming volume change
+ * event to the player instead of changing device stream volume.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public abstract class RemoteSessionPlayer extends SessionPlayer {
     /**
      */
@@ -123,12 +127,16 @@
     public abstract int getVolumeControlType();
 
     /**
-     * A callback class to receive notifications for events on the remote session player. See
-     * {@link #registerPlayerCallback(Executor, PlayerCallback)} to register this callback.
-     * <p>
-     * This is registered by {@link MediaSession} to notify volume changes to the
-     * {@link MediaController}.
+     * A callback class to receive notifications for events on the remote session player. See {@link
+     * #registerPlayerCallback(Executor, PlayerCallback)} to register this callback.
+     *
+     * <p>This is registered by {@link MediaSession} to notify volume changes to the {@link
+     * MediaController}.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static class Callback extends SessionPlayer.PlayerCallback {
         /**
          * Called to indicate that the volume has changed.
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/SessionCommand.java b/media2/media2-session/src/main/java/androidx/media2/session/SessionCommand.java
index 9f00bc8..b3e85f8 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/SessionCommand.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/SessionCommand.java
@@ -46,11 +46,15 @@
 
 /**
  * Defines a command that a {@link MediaController} can send to a {@link MediaSession}.
- * <p>
- * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
- * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
- * {@link #getCustomAction()} shouldn't be {@code null}.
+ *
+ * <p>If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command. If
+ * {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and {@link
+ * #getCustomAction()} shouldn't be {@code null}.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class SessionCommand implements VersionedParcelable {
     /**
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/SessionCommandGroup.java b/media2/media2-session/src/main/java/androidx/media2/session/SessionCommandGroup.java
index 104370c..5a124c2 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/SessionCommandGroup.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/SessionCommandGroup.java
@@ -38,7 +38,11 @@
 
 /**
  * A set of {@link SessionCommand} which represents a command group.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class SessionCommandGroup implements VersionedParcelable {
     private static final String TAG = "SessionCommandGroup";
@@ -121,7 +125,11 @@
 
     /**
      * Builds a {@link SessionCommandGroup} object.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public static final class Builder {
         private Set<SessionCommand> mCommands;
 
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/SessionResult.java b/media2/media2-session/src/main/java/androidx/media2/session/SessionResult.java
index 7625612..151b321 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/SessionResult.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/SessionResult.java
@@ -40,9 +40,13 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Result class to be used with {@link ListenableFuture} for asynchronous calls between
- * {@link MediaSession} and {@link MediaController}.
+ * Result class to be used with {@link ListenableFuture} for asynchronous calls between {@link
+ * MediaSession} and {@link MediaController}.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize(isCustom = true)
 public class SessionResult extends CustomVersionedParcelable implements RemoteResult {
     /**
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/SessionToken.java b/media2/media2-session/src/main/java/androidx/media2/session/SessionToken.java
index 5bf59bf..b6c7f26 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/SessionToken.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/SessionToken.java
@@ -48,13 +48,16 @@
 import java.util.List;
 
 /**
- * Represents an ongoing {@link MediaSession} or a {@link MediaSessionService}.
- * If it's representing a session service, it may not be ongoing.
- * <p>
- * This may be passed to apps by the session owner to allow them to create a
- * {@link MediaController} to communicate with the session.
- * <p>
- * It can be also obtained by {@link MediaSessionManager}.
+ * Represents an ongoing {@link MediaSession} or a {@link MediaSessionService}. If it's representing
+ * a session service, it may not be ongoing.
+ *
+ * <p>This may be passed to apps by the session owner to allow them to create a {@link
+ * MediaController} to communicate with the session.
+ *
+ * <p>It can be also obtained by {@link MediaSessionManager}.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
 // New version of MediaSession.Token for following reasons
 //   - Stop implementing Parcelable for updatable support
@@ -63,6 +66,7 @@
 //     This helps controller apps to keep target of dispatching media key events in uniform way.
 //     For details about the reason, see following. (Android O+)
 //         android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged
+@Deprecated
 @VersionedParcelize
 public final class SessionToken implements VersionedParcelable {
     private static final String TAG = "SessionToken";
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/StarRating.java b/media2/media2-session/src/main/java/androidx/media2/session/StarRating.java
index 168a87d..f2dcef8 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/StarRating.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/StarRating.java
@@ -24,7 +24,11 @@
 
 /**
  * A class for rating expressed as the number of stars.
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class StarRating implements Rating {
     private static final float RATING_NOT_RATED = -1.0f;
diff --git a/media2/media2-session/src/main/java/androidx/media2/session/ThumbRating.java b/media2/media2-session/src/main/java/androidx/media2/session/ThumbRating.java
index 40f3099..2d5989d 100644
--- a/media2/media2-session/src/main/java/androidx/media2/session/ThumbRating.java
+++ b/media2/media2-session/src/main/java/androidx/media2/session/ThumbRating.java
@@ -23,7 +23,11 @@
 
 /**
  * A class for rating with a single degree of rating, "thumb up" vs "thumb down".
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 @VersionedParcelize
 public final class ThumbRating implements Rating {
     @ParcelField(1)
diff --git a/media2/media2-widget/api/current.txt b/media2/media2-widget/api/current.txt
index c21654a..501d5c5 100644
--- a/media2/media2-widget/api/current.txt
+++ b/media2/media2-widget/api/current.txt
@@ -1,37 +1,37 @@
 // Signature format: 4.0
 package androidx.media2.widget {
 
-  public class MediaControlView extends android.view.ViewGroup {
-    ctor public MediaControlView(android.content.Context);
-    ctor public MediaControlView(android.content.Context, android.util.AttributeSet?);
-    ctor public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
-    method public void requestPlayButtonFocus();
-    method public void setMediaController(androidx.media2.session.MediaController);
-    method public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
-    method public void setPlayer(androidx.media2.common.SessionPlayer);
+  @Deprecated public class MediaControlView extends android.view.ViewGroup {
+    ctor @Deprecated public MediaControlView(android.content.Context);
+    ctor @Deprecated public MediaControlView(android.content.Context, android.util.AttributeSet?);
+    ctor @Deprecated public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
+    method @Deprecated public void requestPlayButtonFocus();
+    method @Deprecated public void setMediaController(androidx.media2.session.MediaController);
+    method @Deprecated public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
+    method @Deprecated public void setPlayer(androidx.media2.common.SessionPlayer);
   }
 
-  public static interface MediaControlView.OnFullScreenListener {
-    method public void onFullScreen(android.view.View, boolean);
+  @Deprecated public static interface MediaControlView.OnFullScreenListener {
+    method @Deprecated public void onFullScreen(android.view.View, boolean);
   }
 
-  public class VideoView extends android.view.ViewGroup {
-    ctor public VideoView(android.content.Context);
-    ctor public VideoView(android.content.Context, android.util.AttributeSet?);
-    ctor public VideoView(android.content.Context, android.util.AttributeSet?, int);
-    method public androidx.media2.widget.MediaControlView? getMediaControlView();
-    method public int getViewType();
-    method public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
-    method public void setMediaController(androidx.media2.session.MediaController);
-    method public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
-    method public void setPlayer(androidx.media2.common.SessionPlayer);
-    method public void setViewType(int);
-    field public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
-    field public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
+  @Deprecated public class VideoView extends android.view.ViewGroup {
+    ctor @Deprecated public VideoView(android.content.Context);
+    ctor @Deprecated public VideoView(android.content.Context, android.util.AttributeSet?);
+    ctor @Deprecated public VideoView(android.content.Context, android.util.AttributeSet?, int);
+    method @Deprecated public androidx.media2.widget.MediaControlView? getMediaControlView();
+    method @Deprecated public int getViewType();
+    method @Deprecated public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
+    method @Deprecated public void setMediaController(androidx.media2.session.MediaController);
+    method @Deprecated public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
+    method @Deprecated public void setPlayer(androidx.media2.common.SessionPlayer);
+    method @Deprecated public void setViewType(int);
+    field @Deprecated public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
+    field @Deprecated public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
   }
 
-  public static interface VideoView.OnViewTypeChangedListener {
-    method public void onViewTypeChanged(android.view.View, int);
+  @Deprecated public static interface VideoView.OnViewTypeChangedListener {
+    method @Deprecated public void onViewTypeChanged(android.view.View, int);
   }
 
 }
diff --git a/media2/media2-widget/api/restricted_current.txt b/media2/media2-widget/api/restricted_current.txt
index c21654a..501d5c5 100644
--- a/media2/media2-widget/api/restricted_current.txt
+++ b/media2/media2-widget/api/restricted_current.txt
@@ -1,37 +1,37 @@
 // Signature format: 4.0
 package androidx.media2.widget {
 
-  public class MediaControlView extends android.view.ViewGroup {
-    ctor public MediaControlView(android.content.Context);
-    ctor public MediaControlView(android.content.Context, android.util.AttributeSet?);
-    ctor public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
-    method public void requestPlayButtonFocus();
-    method public void setMediaController(androidx.media2.session.MediaController);
-    method public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
-    method public void setPlayer(androidx.media2.common.SessionPlayer);
+  @Deprecated public class MediaControlView extends android.view.ViewGroup {
+    ctor @Deprecated public MediaControlView(android.content.Context);
+    ctor @Deprecated public MediaControlView(android.content.Context, android.util.AttributeSet?);
+    ctor @Deprecated public MediaControlView(android.content.Context, android.util.AttributeSet?, int);
+    method @Deprecated public void requestPlayButtonFocus();
+    method @Deprecated public void setMediaController(androidx.media2.session.MediaController);
+    method @Deprecated public void setOnFullScreenListener(androidx.media2.widget.MediaControlView.OnFullScreenListener?);
+    method @Deprecated public void setPlayer(androidx.media2.common.SessionPlayer);
   }
 
-  public static interface MediaControlView.OnFullScreenListener {
-    method public void onFullScreen(android.view.View, boolean);
+  @Deprecated public static interface MediaControlView.OnFullScreenListener {
+    method @Deprecated public void onFullScreen(android.view.View, boolean);
   }
 
-  public class VideoView extends android.view.ViewGroup {
-    ctor public VideoView(android.content.Context);
-    ctor public VideoView(android.content.Context, android.util.AttributeSet?);
-    ctor public VideoView(android.content.Context, android.util.AttributeSet?, int);
-    method public androidx.media2.widget.MediaControlView? getMediaControlView();
-    method public int getViewType();
-    method public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
-    method public void setMediaController(androidx.media2.session.MediaController);
-    method public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
-    method public void setPlayer(androidx.media2.common.SessionPlayer);
-    method public void setViewType(int);
-    field public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
-    field public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
+  @Deprecated public class VideoView extends android.view.ViewGroup {
+    ctor @Deprecated public VideoView(android.content.Context);
+    ctor @Deprecated public VideoView(android.content.Context, android.util.AttributeSet?);
+    ctor @Deprecated public VideoView(android.content.Context, android.util.AttributeSet?, int);
+    method @Deprecated public androidx.media2.widget.MediaControlView? getMediaControlView();
+    method @Deprecated public int getViewType();
+    method @Deprecated public void setMediaControlView(androidx.media2.widget.MediaControlView, long);
+    method @Deprecated public void setMediaController(androidx.media2.session.MediaController);
+    method @Deprecated public void setOnViewTypeChangedListener(androidx.media2.widget.VideoView.OnViewTypeChangedListener?);
+    method @Deprecated public void setPlayer(androidx.media2.common.SessionPlayer);
+    method @Deprecated public void setViewType(int);
+    field @Deprecated public static final int VIEW_TYPE_SURFACEVIEW = 0; // 0x0
+    field @Deprecated public static final int VIEW_TYPE_TEXTUREVIEW = 1; // 0x1
   }
 
-  public static interface VideoView.OnViewTypeChangedListener {
-    method public void onViewTypeChanged(android.view.View, int);
+  @Deprecated public static interface VideoView.OnViewTypeChangedListener {
+    method @Deprecated public void onViewTypeChanged(android.view.View, int);
   }
 
 }
diff --git a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithPlayerTest.java b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithPlayerTest.java
index 75dc067..62a867f 100644
--- a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithPlayerTest.java
+++ b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithPlayerTest.java
@@ -40,11 +40,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.media2.common.MediaItem;
-import androidx.media2.common.MediaMetadata;
-import androidx.media2.common.SessionPlayer;
-import androidx.media2.common.SessionPlayer.TrackInfo;
-import androidx.media2.session.MediaController;
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 
@@ -61,8 +56,10 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Test {@link MediaControlView} with a {@link SessionPlayer} or a {@link MediaController}.
+ * Test {@link MediaControlView} with a {@link androidx.media2.common.SessionPlayer} or a {@link
+ * androidx.media2.session.MediaController}.
  */
+@SuppressWarnings("deprecation")
 @RunWith(Parameterized.class)
 @LargeTest
 public class MediaControlView_WithPlayerTest extends MediaWidgetTestBase {
@@ -77,7 +74,7 @@
     private String mPlayerType;
     private MediaControlViewTestActivity mActivity;
     private MediaControlView mMediaControlView;
-    private MediaItem mFileSchemeMediaItem;
+    private androidx.media2.common.MediaItem mFileSchemeMediaItem;
 
     @SuppressWarnings("deprecation")
     @Rule
@@ -120,16 +117,25 @@
     public void setPlayerOrController_PausedState() throws Throwable {
         final CountDownLatch latchForPausedState = new CountDownLatch(1);
         final CountDownLatch latchForPlayingState = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            @Override
-            public void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-                if (state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    latchForPausedState.countDown();
-                } else if (state == SessionPlayer.PLAYER_STATE_PLAYING) {
-                    latchForPlayingState.countDown();
-                }
-            }
-        }, mFileSchemeMediaItem, null);
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            @Override
+                            public void onPlayerStateChanged(
+                                    @NonNull PlayerWrapper player, int state) {
+                                if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PAUSED) {
+                                    latchForPausedState.countDown();
+                                } else if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PLAYING) {
+                                    latchForPlayingState.countDown();
+                                }
+                            }
+                        },
+                        mFileSchemeMediaItem,
+                        null);
         setPlayerWrapper(playerWrapper);
         assertTrue(latchForPausedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         onView(allOf(withId(R.id.pause), isCompletelyDisplayed()))
@@ -148,25 +154,39 @@
         final CountDownLatch latchForPreparedState = new CountDownLatch(1);
         final CountDownLatch latchForPausedState = new CountDownLatch(1);
         final CountDownLatch latchForPlayingState = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            private int mState = SessionPlayer.PLAYER_STATE_IDLE;
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            private int mState =
+                                    androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
 
-            @Override
-            public void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-                if (mState == SessionPlayer.PLAYER_STATE_IDLE
-                        && state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    latchForPreparedState.countDown();
-                }
-                if (state == SessionPlayer.PLAYER_STATE_PLAYING) {
-                    latchForPlayingState.countDown();
-                }
-                if (mState == SessionPlayer.PLAYER_STATE_PLAYING
-                        && state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    latchForPausedState.countDown();
-                }
-                mState = state;
-            }
-        }, mFileSchemeMediaItem, null);
+                            @Override
+                            public void onPlayerStateChanged(
+                                    @NonNull PlayerWrapper player, int state) {
+                                if (mState == androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE
+                                        && state
+                                                == androidx.media2.common.SessionPlayer
+                                                        .PLAYER_STATE_PAUSED) {
+                                    latchForPreparedState.countDown();
+                                }
+                                if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PLAYING) {
+                                    latchForPlayingState.countDown();
+                                }
+                                if (mState
+                                                == androidx.media2.common.SessionPlayer
+                                                        .PLAYER_STATE_PLAYING
+                                        && state
+                                                == androidx.media2.common.SessionPlayer
+                                                        .PLAYER_STATE_PAUSED) {
+                                    latchForPausedState.countDown();
+                                }
+                                mState = state;
+                            }
+                        },
+                        mFileSchemeMediaItem,
+                        null);
         assertTrue(latchForPreparedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         playerWrapper.play();
         assertTrue(latchForPlayingState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
@@ -234,21 +254,29 @@
     public void ffwdButtonClick() throws Throwable {
         final CountDownLatch latchForPausedState = new CountDownLatch(1);
         final CountDownLatch latchForFfwd = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            @Override
-            public void onSeekCompleted(@NonNull PlayerWrapper player, long position) {
-                if (position >= FFWD_MS) {
-                    latchForFfwd.countDown();
-                }
-            }
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            @Override
+                            public void onSeekCompleted(
+                                    @NonNull PlayerWrapper player, long position) {
+                                if (position >= FFWD_MS) {
+                                    latchForFfwd.countDown();
+                                }
+                            }
 
-            @Override
-            public void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-                if (state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    latchForPausedState.countDown();
-                }
-            }
-        }, mFileSchemeMediaItem, null);
+                            @Override
+                            public void onPlayerStateChanged(
+                                    @NonNull PlayerWrapper player, int state) {
+                                if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PAUSED) {
+                                    latchForPausedState.countDown();
+                                }
+                            }
+                        },
+                        mFileSchemeMediaItem,
+                        null);
         setPlayerWrapper(playerWrapper);
         assertTrue(latchForPausedState.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         onView(allOf(withId(R.id.ffwd), isCompletelyDisplayed())).perform(click());
@@ -259,37 +287,47 @@
     public void rewButtonClick() throws Throwable {
         final CountDownLatch latchForFfwd = new CountDownLatch(1);
         final CountDownLatch latchForRew = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            long mExpectedPosition = FFWD_MS;
-            final long mDelta = 1000L;
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            long mExpectedPosition = FFWD_MS;
+                            final long mDelta = 1000L;
 
-            @Override
-            public void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-                if (state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    mExpectedPosition = FFWD_MS;
-                    player.seekTo(mExpectedPosition);
-                }
-            }
+                            @Override
+                            public void onPlayerStateChanged(
+                                    @NonNull PlayerWrapper player, int state) {
+                                if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PAUSED) {
+                                    mExpectedPosition = FFWD_MS;
+                                    player.seekTo(mExpectedPosition);
+                                }
+                            }
 
-            @Override
-            public void onSeekCompleted(@NonNull PlayerWrapper player, long position) {
-                // Ignore the initial seek. Internal MediaPlayer behavior can be changed.
-                if (position == 0 && mExpectedPosition == FFWD_MS) {
-                    return;
-                }
-                assertTrue(equalsSeekPosition(mExpectedPosition, position, mDelta));
-                if (mExpectedPosition == FFWD_MS) {
-                    mExpectedPosition = position - REW_MS;
-                    latchForFfwd.countDown();
-                } else {
-                    latchForRew.countDown();
-                }
-            }
+                            @Override
+                            public void onSeekCompleted(
+                                    @NonNull PlayerWrapper player, long position) {
+                                // Ignore the initial seek. Internal MediaPlayer behavior can be
+                                // changed.
+                                if (position == 0 && mExpectedPosition == FFWD_MS) {
+                                    return;
+                                }
+                                assertTrue(equalsSeekPosition(mExpectedPosition, position, mDelta));
+                                if (mExpectedPosition == FFWD_MS) {
+                                    mExpectedPosition = position - REW_MS;
+                                    latchForFfwd.countDown();
+                                } else {
+                                    latchForRew.countDown();
+                                }
+                            }
 
-            private boolean equalsSeekPosition(long expected, long actual, long delta) {
-                return (actual < expected + delta) && (actual > expected - delta);
-            }
-        }, mFileSchemeMediaItem, null);
+                            private boolean equalsSeekPosition(
+                                    long expected, long actual, long delta) {
+                                return (actual < expected + delta) && (actual > expected - delta);
+                            }
+                        },
+                        mFileSchemeMediaItem,
+                        null);
         setPlayerWrapper(playerWrapper);
         assertTrue(latchForFfwd.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         onView(allOf(withId(R.id.rew), isCompletelyDisplayed())).perform(click());
@@ -299,7 +337,7 @@
     @Test
     public void prevNextButtonClick() throws Throwable {
         DefaultPlayerCallback callback = new DefaultPlayerCallback();
-        final List<MediaItem> playlist = createTestPlaylist();
+        final List<androidx.media2.common.MediaItem> playlist = createTestPlaylist();
         final PlayerWrapper playerWrapper = createPlayerWrapper(callback, null, playlist);
         setPlayerWrapper(playerWrapper);
 
@@ -338,26 +376,37 @@
         final String title = "BigBuckBunny";
         final CountDownLatch latch = new CountDownLatch(1);
 
-        MediaMetadata existingMetadata = mFileSchemeMediaItem.getMetadata();
-        MediaMetadata.Builder metadataBuilder = existingMetadata == null
-                ? new MediaMetadata.Builder()
-                : new MediaMetadata.Builder(existingMetadata);
-        MediaMetadata metadata = metadataBuilder
-                .putString(MediaMetadata.METADATA_KEY_TITLE, title)
-                .build();
+        androidx.media2.common.MediaMetadata existingMetadata = mFileSchemeMediaItem.getMetadata();
+        androidx.media2.common.MediaMetadata.Builder metadataBuilder =
+                existingMetadata == null
+                        ? new androidx.media2.common.MediaMetadata.Builder()
+                        : new androidx.media2.common.MediaMetadata.Builder(existingMetadata);
+        androidx.media2.common.MediaMetadata metadata =
+                metadataBuilder
+                        .putString(androidx.media2.common.MediaMetadata.METADATA_KEY_TITLE, title)
+                        .build();
         mFileSchemeMediaItem.setMetadata(metadata);
 
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            @Override
-            public void onCurrentMediaItemChanged(@NonNull PlayerWrapper player,
-                    @Nullable MediaItem item) {
-                if (item != null) {
-                    assertNotNull(item.getMetadata());
-                    assertEquals(title, metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
-                    latch.countDown();
-                }
-            }
-        }, mFileSchemeMediaItem, null);
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            @Override
+                            public void onCurrentMediaItemChanged(
+                                    @NonNull PlayerWrapper player,
+                                    @Nullable androidx.media2.common.MediaItem item) {
+                                if (item != null) {
+                                    assertNotNull(item.getMetadata());
+                                    assertEquals(
+                                            title,
+                                            metadata.getString(
+                                                    androidx.media2.common.MediaMetadata
+                                                            .METADATA_KEY_TITLE));
+                                    latch.countDown();
+                                }
+                            }
+                        },
+                        mFileSchemeMediaItem,
+                        null);
         setPlayerWrapper(playerWrapper);
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         onView(withId(R.id.title_text)).check(matches(withText(title)));
@@ -366,20 +415,29 @@
     @Test
     public void subtitleButtonVisibilityForMusicFile() throws Throwable {
         Uri uri = getResourceUri(androidx.media2.widget.test.R.raw.test_music);
-        final MediaItem uriMediaItem = createTestMediaItem(uri);
+        final androidx.media2.common.MediaItem uriMediaItem = createTestMediaItem(uri);
 
         final CountDownLatch latch = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            @Override
-            void onTracksChanged(@NonNull PlayerWrapper player, @NonNull List<TrackInfo> tracks) {
-                assertNotNull(tracks);
-                if (tracks.isEmpty()) {
-                    // This callback can be called before tracks are available after setMediaItem
-                    return;
-                }
-                latch.countDown();
-            }
-        }, uriMediaItem, null);
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            @Override
+                            void onTracksChanged(
+                                    @NonNull PlayerWrapper player,
+                                    @NonNull
+                                            List<androidx.media2.common.SessionPlayer.TrackInfo>
+                                                    tracks) {
+                                assertNotNull(tracks);
+                                if (tracks.isEmpty()) {
+                                    // This callback can be called before tracks are available after
+                                    // setandroidx.media2.common.MediaItem
+                                    return;
+                                }
+                                latch.countDown();
+                            }
+                        },
+                        uriMediaItem,
+                        null);
         setPlayerWrapper(playerWrapper);
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         onView(withId(R.id.subtitle)).check(matches(not(isDisplayed())));
@@ -395,52 +453,73 @@
         final String subtitleTrack1Text = mContext.getResources().getString(
                 R.string.MediaControlView_subtitle_track_number_text, 1);
 
-        final MediaItem mediaItem = createTestMediaItem(uri);
+        final androidx.media2.common.MediaItem mediaItem = createTestMediaItem(uri);
 
         final CountDownLatch latchForReady = new CountDownLatch(1);
         final CountDownLatch latchForTrackUpdate = new CountDownLatch(1);
         final CountDownLatch latchForSubtitleSelect = new CountDownLatch(1);
         final CountDownLatch latchForSubtitleDeselect = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            private TrackInfo mFirstSubtitleTrack;
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            private androidx.media2.common.SessionPlayer.TrackInfo
+                                    mFirstSubtitleTrack;
 
-            @Override
-            public void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-                if (state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    latchForReady.countDown();
-                }
-            }
+                            @Override
+                            public void onPlayerStateChanged(
+                                    @NonNull PlayerWrapper player, int state) {
+                                if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PAUSED) {
+                                    latchForReady.countDown();
+                                }
+                            }
 
-            @Override
-            void onTracksChanged(@NonNull PlayerWrapper player, @NonNull List<TrackInfo> tracks) {
-                if (mFirstSubtitleTrack != null) {
-                    return;
-                }
-                assertNotNull(tracks);
-                for (int i = 0; i < tracks.size(); i++) {
-                    TrackInfo trackInfo = tracks.get(i);
-                    if (trackInfo.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
-                        mFirstSubtitleTrack = trackInfo;
-                        latchForTrackUpdate.countDown();
-                        break;
-                    }
-                }
-            }
+                            @Override
+                            void onTracksChanged(
+                                    @NonNull PlayerWrapper player,
+                                    @NonNull
+                                            List<androidx.media2.common.SessionPlayer.TrackInfo>
+                                                    tracks) {
+                                if (mFirstSubtitleTrack != null) {
+                                    return;
+                                }
+                                assertNotNull(tracks);
+                                for (int i = 0; i < tracks.size(); i++) {
+                                    androidx.media2.common.SessionPlayer.TrackInfo trackInfo =
+                                            tracks.get(i);
+                                    if (trackInfo.getTrackType()
+                                            == androidx.media2.common.SessionPlayer.TrackInfo
+                                                    .MEDIA_TRACK_TYPE_SUBTITLE) {
+                                        mFirstSubtitleTrack = trackInfo;
+                                        latchForTrackUpdate.countDown();
+                                        break;
+                                    }
+                                }
+                            }
 
-            @Override
-            public void onTrackSelected(@NonNull PlayerWrapper player,
-                    @NonNull TrackInfo trackInfo) {
-                assertEquals(mFirstSubtitleTrack, trackInfo);
-                latchForSubtitleSelect.countDown();
-            }
+                            @Override
+                            public void onTrackSelected(
+                                    @NonNull PlayerWrapper player,
+                                    @NonNull
+                                            androidx.media2.common.SessionPlayer.TrackInfo
+                                                    trackInfo) {
+                                assertEquals(mFirstSubtitleTrack, trackInfo);
+                                latchForSubtitleSelect.countDown();
+                            }
 
-            @Override
-            public void onTrackDeselected(@NonNull PlayerWrapper player,
-                    @NonNull TrackInfo trackInfo) {
-                assertEquals(mFirstSubtitleTrack, trackInfo);
-                latchForSubtitleDeselect.countDown();
-            }
-        }, mediaItem, null);
+                            @Override
+                            public void onTrackDeselected(
+                                    @NonNull PlayerWrapper player,
+                                    @NonNull
+                                            androidx.media2.common.SessionPlayer.TrackInfo
+                                                    trackInfo) {
+                                assertEquals(mFirstSubtitleTrack, trackInfo);
+                                latchForSubtitleDeselect.countDown();
+                            }
+                        },
+                        mediaItem,
+                        null);
         setPlayerWrapper(playerWrapper);
         assertTrue(latchForReady.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         // MediaPlayer needs a surface to be set in order to produce subtitle tracks
@@ -466,16 +545,25 @@
     public void attachViewAndPlayAfterSetPlayerOrController() throws Throwable {
         final CountDownLatch latchForPausedState = new CountDownLatch(1);
         final CountDownLatch latchForPlayingState = new CountDownLatch(1);
-        final PlayerWrapper playerWrapper = createPlayerWrapper(new PlayerWrapper.PlayerCallback() {
-            @Override
-            public void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-                if (state == SessionPlayer.PLAYER_STATE_PAUSED) {
-                    latchForPausedState.countDown();
-                } else if (state == SessionPlayer.PLAYER_STATE_PLAYING) {
-                    latchForPlayingState.countDown();
-                }
-            }
-        }, mFileSchemeMediaItem, null);
+        final PlayerWrapper playerWrapper =
+                createPlayerWrapper(
+                        new PlayerWrapper.PlayerCallback() {
+                            @Override
+                            public void onPlayerStateChanged(
+                                    @NonNull PlayerWrapper player, int state) {
+                                if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PAUSED) {
+                                    latchForPausedState.countDown();
+                                } else if (state
+                                        == androidx.media2.common.SessionPlayer
+                                                .PLAYER_STATE_PLAYING) {
+                                    latchForPlayingState.countDown();
+                                }
+                            }
+                        },
+                        mFileSchemeMediaItem,
+                        null);
         mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -514,8 +602,10 @@
         });
     }
 
-    private PlayerWrapper createPlayerWrapper(@NonNull PlayerWrapper.PlayerCallback callback,
-            @Nullable MediaItem item, @Nullable List<MediaItem> playlist) {
+    private PlayerWrapper createPlayerWrapper(
+            @NonNull PlayerWrapper.PlayerCallback callback,
+            @Nullable androidx.media2.common.MediaItem item,
+            @Nullable List<androidx.media2.common.MediaItem> playlist) {
         return createPlayerWrapperOfType(callback, item, playlist, mPlayerType);
     }
 }
diff --git a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithoutPlayerTest.java b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithoutPlayerTest.java
index d90a643..2db77e9 100644
--- a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithoutPlayerTest.java
+++ b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaControlView_WithoutPlayerTest.java
@@ -43,9 +43,10 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Test {@link MediaControlView} without any {@link androidx.media2.common.SessionPlayer} or
- * {@link androidx.media2.session.MediaController}.
+ * Test {@link MediaControlView} without any {@link androidx.media2.common.SessionPlayer} or {@link
+ * androidx.media2.session.MediaController}.
  */
+@SuppressWarnings("deprecation")
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class MediaControlView_WithoutPlayerTest extends MediaWidgetTestBase {
diff --git a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaWidgetTestBase.java b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaWidgetTestBase.java
index 232b8e1..fcf4b40 100644
--- a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaWidgetTestBase.java
+++ b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/MediaWidgetTestBase.java
@@ -29,13 +29,6 @@
 import androidx.annotation.Nullable;
 import androidx.core.content.ContextCompat;
 import androidx.core.view.ViewCompat;
-import androidx.media2.common.MediaItem;
-import androidx.media2.common.MediaMetadata;
-import androidx.media2.common.SessionPlayer;
-import androidx.media2.common.UriMediaItem;
-import androidx.media2.player.MediaPlayer;
-import androidx.media2.session.MediaController;
-import androidx.media2.session.MediaSession;
 import androidx.media2.widget.test.R;
 import androidx.test.core.app.ApplicationProvider;
 
@@ -49,21 +42,25 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
+@SuppressWarnings("deprecation")
 public class MediaWidgetTestBase extends MediaTestBase {
-    static final String PLAYER_TYPE_MEDIA_CONTROLLER = "MediaController";
-    static final String PLAYER_TYPE_MEDIA_PLAYER = "MediaPlayer";
+    static final String PLAYER_TYPE_MEDIA_CONTROLLER = "androidx.media2.session.MediaController";
+    static final String PLAYER_TYPE_MEDIA_PLAYER = "androidx.media2.player.MediaPlayer";
 
     // Expected success time
     // Increased timeout to pass on old devices (ex. Nexus4 API 17)
     static final int WAIT_TIME_MS = 2000;
 
     private final Object mLock = new Object();
+
     @GuardedBy("mLock")
-    private List<SessionPlayer> mPlayers = new ArrayList<>();
+    private List<androidx.media2.common.SessionPlayer> mPlayers = new ArrayList<>();
+
     @GuardedBy("mLock")
-    private List<MediaSession> mSessions = new ArrayList<>();
+    private List<androidx.media2.session.MediaSession> mSessions = new ArrayList<>();
+
     @GuardedBy("mLock")
-    private List<MediaController> mControllers = new ArrayList<>();
+    private List<androidx.media2.session.MediaController> mControllers = new ArrayList<>();
 
     Context mContext;
     Executor mMainHandlerExecutor;
@@ -93,26 +90,26 @@
         }
     }
 
-    MediaItem createTestMediaItem() {
+    androidx.media2.common.MediaItem createTestMediaItem() {
         Uri testVideoUri = getResourceUri(R.raw.testvideo_with_2_subtitle_tracks);
         return createTestMediaItem(testVideoUri);
     }
 
-    MediaItem createTestMediaItem(Uri uri) {
+    androidx.media2.common.MediaItem createTestMediaItem(Uri uri) {
         return createTestMediaItem(uri, "defaultMediaId");
     }
 
-    MediaItem createTestMediaItem(Uri uri, String mediaId) {
-        MediaMetadata metadata = new MediaMetadata.Builder()
-                .putText(MediaMetadata.METADATA_KEY_MEDIA_ID, mediaId)
-                .build();
-        return new UriMediaItem.Builder(uri)
-                .setMetadata(metadata)
-                .build();
+    androidx.media2.common.MediaItem createTestMediaItem(Uri uri, String mediaId) {
+        androidx.media2.common.MediaMetadata metadata =
+                new androidx.media2.common.MediaMetadata.Builder()
+                        .putText(
+                                androidx.media2.common.MediaMetadata.METADATA_KEY_MEDIA_ID, mediaId)
+                        .build();
+        return new androidx.media2.common.UriMediaItem.Builder(uri).setMetadata(metadata).build();
     }
 
-    List<MediaItem> createTestPlaylist() {
-        List<MediaItem> list = new ArrayList<>();
+    List<androidx.media2.common.MediaItem> createTestPlaylist() {
+        List<androidx.media2.common.MediaItem> list = new ArrayList<>();
         list.add(createTestMediaItem(getResourceUri(R.raw.test_file_scheme_video), "id_1"));
         list.add(createTestMediaItem(getResourceUri(R.raw.test_music), "id_2"));
         list.add(createTestMediaItem(getResourceUri(R.raw.testvideo_with_2_subtitle_tracks),
@@ -125,16 +122,23 @@
     }
 
     @SuppressWarnings("FutureReturnValueIgnored")
-    PlayerWrapper createPlayerWrapperOfController(@NonNull PlayerWrapper.PlayerCallback callback,
-            @Nullable MediaItem item, @Nullable List<MediaItem> playlist) {
-        SessionPlayer player = new MediaPlayer(mContext);
-        MediaSession session = new MediaSession.Builder(mContext, player)
-                .setId(UUID.randomUUID().toString())
-                .setSessionCallback(mSessionCallbackExecutor, new MediaSession.SessionCallback() {})
-                .build();
-        MediaController controller = new MediaController.Builder(mContext)
-                .setSessionToken(session.getToken())
-                .build();
+    PlayerWrapper createPlayerWrapperOfController(
+            @NonNull PlayerWrapper.PlayerCallback callback,
+            @Nullable androidx.media2.common.MediaItem item,
+            @Nullable List<androidx.media2.common.MediaItem> playlist) {
+        androidx.media2.common.SessionPlayer player =
+                new androidx.media2.player.MediaPlayer(mContext);
+        androidx.media2.session.MediaSession session =
+                new androidx.media2.session.MediaSession.Builder(mContext, player)
+                        .setId(UUID.randomUUID().toString())
+                        .setSessionCallback(
+                                mSessionCallbackExecutor,
+                                new androidx.media2.session.MediaSession.SessionCallback() {})
+                        .build();
+        androidx.media2.session.MediaController controller =
+                new androidx.media2.session.MediaController.Builder(mContext)
+                        .setSessionToken(session.getToken())
+                        .build();
         synchronized (mLock) {
             mPlayers.add(player);
             mSessions.add(session);
@@ -153,9 +157,12 @@
     }
 
     @SuppressWarnings("FutureReturnValueIgnored")
-    PlayerWrapper createPlayerWrapperOfPlayer(@NonNull PlayerWrapper.PlayerCallback callback,
-            @Nullable MediaItem item, @Nullable List<MediaItem> playlist) {
-        SessionPlayer player = new MediaPlayer(mContext);
+    PlayerWrapper createPlayerWrapperOfPlayer(
+            @NonNull PlayerWrapper.PlayerCallback callback,
+            @Nullable androidx.media2.common.MediaItem item,
+            @Nullable List<androidx.media2.common.MediaItem> playlist) {
+        androidx.media2.common.SessionPlayer player =
+                new androidx.media2.player.MediaPlayer(mContext);
         synchronized (mLock) {
             mPlayers.add(player);
         }
@@ -171,8 +178,10 @@
         return wrapper;
     }
 
-    PlayerWrapper createPlayerWrapperOfType(@NonNull PlayerWrapper.PlayerCallback callback,
-            @Nullable MediaItem item, @Nullable List<MediaItem> playlist,
+    PlayerWrapper createPlayerWrapperOfType(
+            @NonNull PlayerWrapper.PlayerCallback callback,
+            @Nullable androidx.media2.common.MediaItem item,
+            @Nullable List<androidx.media2.common.MediaItem> playlist,
             @NonNull String playerType) {
         if (PLAYER_TYPE_MEDIA_CONTROLLER.equals(playerType)) {
             return createPlayerWrapperOfController(callback, item, playlist);
@@ -185,13 +194,13 @@
 
     void closeAll() {
         synchronized (mLock) {
-            for (MediaController controller : mControllers) {
+            for (androidx.media2.session.MediaController controller : mControllers) {
                 controller.close();
             }
-            for (MediaSession session : mSessions) {
+            for (androidx.media2.session.MediaSession session : mSessions) {
                 session.close();
             }
-            for (SessionPlayer player : mPlayers) {
+            for (androidx.media2.common.SessionPlayer player : mPlayers) {
                 try {
                     player.close();
                 } catch (Exception ex) {
@@ -211,8 +220,8 @@
         String mPrevId = "placeholderId";
 
         @Override
-        void onCurrentMediaItemChanged(@NonNull PlayerWrapper player,
-                @Nullable MediaItem item) {
+        void onCurrentMediaItemChanged(
+                @NonNull PlayerWrapper player, @Nullable androidx.media2.common.MediaItem item) {
             if (item != null && !TextUtils.equals(mPrevId, item.getMediaId())) {
                 mPrevId = item.getMediaId();
                 mItemLatch.countDown();
@@ -221,9 +230,9 @@
 
         @Override
         void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
-            if (state == SessionPlayer.PLAYER_STATE_PAUSED) {
+            if (state == androidx.media2.common.SessionPlayer.PLAYER_STATE_PAUSED) {
                 mPausedLatch.countDown();
-            } else if (state == SessionPlayer.PLAYER_STATE_PLAYING) {
+            } else if (state == androidx.media2.common.SessionPlayer.PLAYER_STATE_PLAYING) {
                 mPlayingLatch.countDown();
             }
         }
diff --git a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java
index a94604b..b4df7e5 100644
--- a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java
+++ b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithPlayerTest.java
@@ -45,11 +45,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
-import androidx.media2.common.FileMediaItem;
-import androidx.media2.common.MediaItem;
-import androidx.media2.common.SessionPlayer;
-import androidx.media2.common.VideoSize;
-import androidx.media2.session.MediaController;
 import androidx.media2.widget.test.R;
 import androidx.test.filters.LargeTest;
 
@@ -66,8 +61,10 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Test {@link VideoView} with a {@link SessionPlayer} or a {@link MediaController}.
+ * Test {@link VideoView} with a {@link androidx.media2.common.SessionPlayer} or a {@link
+ * androidx.media2.session.MediaController}.
  */
+@SuppressWarnings("deprecation")
 @RunWith(Parameterized.class)
 @LargeTest
 public class VideoView_WithPlayerTest extends MediaWidgetTestBase {
@@ -79,7 +76,7 @@
     private String mPlayerType;
     private Activity mActivity;
     private VideoView mVideoView;
-    private MediaItem mMediaItem;
+    private androidx.media2.common.MediaItem mMediaItem;
     private SynchronousPixelCopy mPixelCopyHelper;
 
     @SuppressWarnings("deprecation")
@@ -126,7 +123,9 @@
         assertTrue(callback.mItemLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         assertTrue(callback.mPausedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
         assertEquals(1, callback.mPlayingLatch.getCount());
-        assertEquals(SessionPlayer.PLAYER_STATE_PAUSED, playerWrapper.getPlayerState());
+        assertEquals(
+                androidx.media2.common.SessionPlayer.PLAYER_STATE_PAUSED,
+                playerWrapper.getPlayerState());
 
         playerWrapper.play();
         assertTrue(callback.mPlayingLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
@@ -137,11 +136,12 @@
     public void playVideoWithMediaItemFromFileDescriptor() throws Throwable {
         AssetFileDescriptor afd = mContext.getResources()
                 .openRawResourceFd(R.raw.testvideo_with_2_subtitle_tracks);
-        final MediaItem item = new FileMediaItem.Builder(
-                ParcelFileDescriptor.dup(afd.getFileDescriptor()))
-                .setFileDescriptorOffset(afd.getStartOffset())
-                .setFileDescriptorLength(afd.getLength())
-                .build();
+        final androidx.media2.common.MediaItem item =
+                new androidx.media2.common.FileMediaItem.Builder(
+                                ParcelFileDescriptor.dup(afd.getFileDescriptor()))
+                        .setFileDescriptorOffset(afd.getStartOffset())
+                        .setFileDescriptorLength(afd.getLength())
+                        .build();
         afd.close();
 
         DefaultPlayerCallback callback = new DefaultPlayerCallback();
@@ -342,8 +342,10 @@
 
     @Test
     public void aspectRatioOfSurfaceView() throws Throwable {
-        MediaItem testMediaItem = createTestMediaItem(getResourceUri(R.raw.test_file_scheme_video));
-        VideoSize testVideoSize = new VideoSize(352, 288);
+        androidx.media2.common.MediaItem testMediaItem =
+                createTestMediaItem(getResourceUri(R.raw.test_file_scheme_video));
+        androidx.media2.common.VideoSize testVideoSize =
+                new androidx.media2.common.VideoSize(352, 288);
         CountDownLatch latch = new CountDownLatch(1);
 
         mActivityRule.runOnUiThread(() -> {
@@ -375,7 +377,8 @@
                 withAspectRatio(testVideoSize.getWidth(), testVideoSize.getHeight())));
 
         // Unable to test the case for multiple media items with different aspect ratio due to the
-        // flakiness of onVideoSizeChanged of MediaPlayer (b/144876689, b/144972397)
+        // flakiness of onandroidx.media2.common.VideoSizeChanged of MediaPlayer (b/144876689,
+        // b/144972397)
     }
 
     private void setPlayerWrapper(final PlayerWrapper playerWrapper) throws Throwable {
@@ -391,8 +394,10 @@
         });
     }
 
-    private PlayerWrapper createPlayerWrapper(@NonNull PlayerWrapper.PlayerCallback callback,
-            @Nullable MediaItem item, @Nullable List<MediaItem> playlist) {
+    private PlayerWrapper createPlayerWrapper(
+            @NonNull PlayerWrapper.PlayerCallback callback,
+            @Nullable androidx.media2.common.MediaItem item,
+            @Nullable List<androidx.media2.common.MediaItem> playlist) {
         return createPlayerWrapperOfType(callback, item, playlist, mPlayerType);
     }
 
diff --git a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithoutPlayerTest.java b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithoutPlayerTest.java
index 33abeb9..691a1f7 100644
--- a/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithoutPlayerTest.java
+++ b/media2/media2-widget/src/androidTest/java/androidx/media2/widget/VideoView_WithoutPlayerTest.java
@@ -31,9 +31,10 @@
 import org.junit.runner.RunWith;
 
 /**
- * Test {@link VideoView} without any {@link androidx.media2.common.SessionPlayer} or
- * {@link androidx.media2.session.MediaController}.
+ * Test {@link VideoView} without any {@link androidx.media2.common.SessionPlayer} or {@link
+ * androidx.media2.session.MediaController}.
  */
+@SuppressWarnings("deprecation")
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class VideoView_WithoutPlayerTest extends MediaWidgetTestBase {
diff --git a/media2/media2-widget/src/main/java/androidx/media2/widget/MediaControlView.java b/media2/media2-widget/src/main/java/androidx/media2/widget/MediaControlView.java
index 9e7b110..6ef9ac9 100644
--- a/media2/media2-widget/src/main/java/androidx/media2/widget/MediaControlView.java
+++ b/media2/media2-widget/src/main/java/androidx/media2/widget/MediaControlView.java
@@ -52,16 +52,6 @@
 import androidx.appcompat.app.AlertDialog;
 import androidx.core.content.ContextCompat;
 import androidx.core.view.ViewCompat;
-import androidx.media2.common.MediaItem;
-import androidx.media2.common.MediaMetadata;
-import androidx.media2.common.SessionPlayer;
-import androidx.media2.common.SessionPlayer.TrackInfo;
-import androidx.media2.common.UriMediaItem;
-import androidx.media2.common.VideoSize;
-import androidx.media2.session.MediaController;
-import androidx.media2.session.MediaSession;
-import androidx.media2.session.SessionCommand;
-import androidx.media2.session.SessionCommandGroup;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -70,91 +60,112 @@
 import java.util.Locale;
 
 /**
- * A View that contains the controls for {@link MediaController} or {@link SessionPlayer}.
- * It provides a wide range of buttons that serve the following functions: play/pause,
- * rewind/fast-forward, skip to next/previous, select subtitle track, enter/exit full screen mode,
- * select audio track, and adjust playback speed.
+ * A View that contains the controls for {@link androidx.media2.session.MediaController} or {@link
+ * androidx.media2.common.SessionPlayer}. It provides a wide range of buttons that serve the
+ * following functions: play/pause, rewind/fast-forward, skip to next/previous, select subtitle
+ * track, enter/exit full screen mode, select audio track, and adjust playback speed.
+ *
+ * <p>For simple use cases not requiring communication with {@link
+ * androidx.media2.session.MediaSession}, apps need to create a {@link
+ * androidx.media2.common.SessionPlayer} (e.g. {@link androidx.media2.player.MediaPlayer}) and set
+ * it to this view by calling {@link #setPlayer}. For more advanced use cases that require {@link
+ * androidx.media2.session.MediaSession} (e.g. handling media key events, integrating with other
+ * androidx.media2.session.MediaSession apps as Assistant), apps need to create a {@link
+ * androidx.media2.session.MediaController} attached to the {@link
+ * androidx.media2.session.MediaSession} and set it to this view by calling {@link
+ * #setMediaController}.
+ *
+ * <p>The easiest way to use a MediaControlView is by creating a {@link VideoView}, which internally
+ * creates a MediaControlView instance and handles all the commands from buttons inside
+ * MediaControlView. It is also possible to create a MediaControlView programmatically and add it to
+ * a custom video view. For more information, refer to {@link VideoView}.
+ *
+ * <p>By default, each button in the MediaControlView is visible only when its corresponding {@link
+ * androidx.media2.session.SessionCommand} is included in the active {@link
+ * androidx.media2.session.SessionCommandGroup}. For more details, refer to {@link
+ * androidx.media2.session.MediaSession#setAllowedCommands}.
+ *
  * <p>
- * For simple use cases not requiring communication with {@link MediaSession}, apps need to create
- * a {@link SessionPlayer} (e.g. {@link androidx.media2.player.MediaPlayer}) and set it to this view
- * by calling {@link #setPlayer}.
- * For more advanced use cases that require {@link MediaSession} (e.g. handling media key events,
- * integrating with other MediaSession apps as Assistant), apps need to create
- * a {@link MediaController} attached to the {@link MediaSession} and set it to this view
- * by calling {@link #setMediaController}.
- * <p>
- * The easiest way to use a MediaControlView is by creating a {@link VideoView}, which
- * internally creates a MediaControlView instance and handles all the commands from buttons inside
- * MediaControlView. It is also possible to create a MediaControlView programmatically and add it
- * to a custom video view. For more information, refer to {@link VideoView}.
- * <p>
- * By default, each button in the MediaControlView is visible only when its corresponding
- * {@link SessionCommand} is included in the active {@link SessionCommandGroup}.
- * For more details, refer to {@link MediaSession#setAllowedCommands}.
- * <p>
+ *
  * <h3>UI transitions</h3>
+ *
  * The UI of an app can be in one of three modes:
+ *
  * <ul>
- *     <li>In <b>full</b> mode all the views, such as progress bar, title, transport controls,
- *     and other icons are visible.
- *     <li>In <b>progress-bar only</b> mode the progress bar is the only visible element.
- *     The title, transport controls, and other icons are hidden.
- *     <li>In <b>None</b> mode all the views are hidden.
+ *   <li>In <b>full</b> mode all the views, such as progress bar, title, transport controls, and
+ *       other icons are visible.
+ *   <li>In <b>progress-bar only</b> mode the progress bar is the only visible element. The title,
+ *       transport controls, and other icons are hidden.
+ *   <li>In <b>None</b> mode all the views are hidden.
  * </ul>
- * When the  UI mode changes, MediaControlView animates the transition. The animation does not
- * start immediately, there is a default delay interval of 2000ms before the animation begins. You
- * can change this interval by calling
- * {@link VideoView#setMediaControlView(MediaControlView, long)}.
- * <p>
- * User actions can change the scheduled transition during the delay interval according to
- * the following logic:
+ *
+ * When the UI mode changes, MediaControlView animates the transition. The animation does not start
+ * immediately, there is a default delay interval of 2000ms before the animation begins. You can
+ * change this interval by calling {@link VideoView#setMediaControlView(MediaControlView, long)}.
+ *
+ * <p>User actions can change the scheduled transition during the delay interval according to the
+ * following logic:
+ *
  * <ol>
- *   <li> In Full mode
- *   <ul>
- *       <li>If a touch/trackball event is received during the interval, the UI changes to None
- *       mode.
- *       <li>If no touch/trackball event is received during the interval, the UI changes to
- *       progress-bar only mode.
- *   </ul>
- *   <li> In Progress-bar only mode
- *   <ul>
- *     <li>If a touch/trackball event is received, the UI changes to Full mode.
- *     <li>If no touch/trackball event is received, the UI changes to None mode.
- *   </ul>
- *   <li> In None mode, if a touch/trackball event is received, the UI changes to Full mode.
+ *   <li>In Full mode
+ *       <ul>
+ *         <li>If a touch/trackball event is received during the interval, the UI changes to None
+ *             mode.
+ *         <li>If no touch/trackball event is received during the interval, the UI changes to
+ *             progress-bar only mode.
+ *       </ul>
+ *   <li>In Progress-bar only mode
+ *       <ul>
+ *         <li>If a touch/trackball event is received, the UI changes to Full mode.
+ *         <li>If no touch/trackball event is received, the UI changes to None mode.
+ *       </ul>
+ *   <li>In None mode, if a touch/trackball event is received, the UI changes to Full mode.
  * </ol>
+ *
  * All touch/trackballs events are ignored while the system is animating the change between modes.
+ *
  * <p>
+ *
  * <h3>Customization</h3>
+ *
  * The following customizations are supported:
+ *
  * <ul>
  *   <li>Set focus to the play/pause button by calling {@link #requestPlayButtonFocus()}.
  *   <li>Set full screen behavior by calling {@link #setOnFullScreenListener(OnFullScreenListener)}.
- *   Calling this method will also show the full screen button.
+ *       Calling this method will also show the full screen button.
  * </ul>
+ *
  * <p>
+ *
  * <h3>Displaying metadata</h3>
- * MediaControlView supports displaying metadata by calling
- * {@link MediaItem#setMetadata(MediaMetadata)}.
- * Metadata display is different for two different media types: video (with or without sound)
- * and audio(sound only, no video)
- * <p>
- * The following table shows the metadata displayed on VideoView and the default
- * values assigned if the keys are not set:
+ *
+ * MediaControlView supports displaying metadata by calling {@link
+ * androidx.media2.common.MediaItem#setMetadata(androidx.media2.common.MediaMetadata)}. Metadata
+ * display is different for two different media types: video (with or without sound) and audio(sound
+ * only, no video)
+ *
+ * <p>The following table shows the metadata displayed on VideoView and the default values assigned
+ * if the keys are not set:
+ *
  * <table>
  *     <tr><th>Key</th><th>Default</th></tr>
- *     <tr><td>{@link MediaMetadata#METADATA_KEY_TITLE}</td>
+ *     <tr><td>{@link androidx.media2.common.MediaMetadata#METADATA_KEY_TITLE}</td>
  *     <td>{@link androidx.media2.widget.R.string#mcv2_music_title_unknown_text}</td></tr>
- *     <tr><td>{@link MediaMetadata#METADATA_KEY_ARTIST}</td>
+ *     <tr><td>{@link androidx.media2.common.MediaMetadata#METADATA_KEY_ARTIST}</td>
  *     <td>{@link androidx.media2.widget.R.string#mcv2_music_artist_unknown_text}</td></tr>
- *     <tr><td>{@link MediaMetadata#METADATA_KEY_ALBUM_ART}</td>
+ *     <tr><td>{@link androidx.media2.common.MediaMetadata#METADATA_KEY_ALBUM_ART}</td>
  *     <td>{@link androidx.media2.widget.R.drawable#media2_widget_ic_default_album_image}</td></tr>
  *     </table>
- * <p>
- * For video media, {@link MediaMetadata#METADATA_KEY_TITLE} metadata is supported.
- * If the value is not set, the following default value will be shown:
- * {@link androidx.media2.widget.R.string#mcv2_non_music_title_unknown_text}
+ *
+ * <p>For video media, {@link androidx.media2.common.MediaMetadata#METADATA_KEY_TITLE} metadata is
+ * supported. If the value is not set, the following default value will be shown: {@link
+ * androidx.media2.widget.R.string#mcv2_non_music_title_unknown_text}
+ *
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class MediaControlView extends MediaViewGroup {
     private static final String TAG = "MediaControlView";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -279,8 +290,8 @@
     private List<Integer> mSettingsIconIdsList;
     List<String> mSubtitleDescriptionsList;
     int mVideoTrackCount;
-    List<TrackInfo> mAudioTracks = new ArrayList<>();
-    List<TrackInfo> mSubtitleTracks = new ArrayList<>();
+    List<androidx.media2.common.SessionPlayer.TrackInfo> mAudioTracks = new ArrayList<>();
+    List<androidx.media2.common.SessionPlayer.TrackInfo> mSubtitleTracks = new ArrayList<>();
     List<String> mAudioTrackDescriptionList;
     List<String> mPlaybackSpeedTextList;
     List<Integer> mPlaybackSpeedMultBy100List;
@@ -315,22 +326,24 @@
     }
 
     /**
-     * Sets {@link MediaController} to control playback with this view.
-     * Setting a MediaController will unset any MediaController or SessionPlayer
-     * that was previously set.
-     * <p>
-     * It will throw {@link IllegalStateException} if this MediaControlView belongs to
-     * a {@link VideoView} by {@link androidx.media2.widget.R.attr#enableControlView} or
-     * by {@link VideoView#setMediaControlView}. Use {@link VideoView#setMediaController} instead.
-     * <p>
-     * Note that MediaControlView allows controlling playback through its UI components, but calling
-     * the corresponding methods (e.g. {@link MediaController#play()},
-     * {@link MediaController#pause()}) will work as well.
+     * Sets {@link androidx.media2.session.MediaController} to control playback with this view.
+     * Setting a androidx.media2.session.MediaController will unset any
+     * androidx.media2.session.MediaController or androidx.media2.common.SessionPlayer that was
+     * previously set.
+     *
+     * <p>It will throw {@link IllegalStateException} if this MediaControlView belongs to a {@link
+     * VideoView} by {@link androidx.media2.widget.R.attr#enableControlView} or by {@link
+     * VideoView#setMediaControlView}. Use {@link VideoView#setMediaController} instead.
+     *
+     * <p>Note that MediaControlView allows controlling playback through its UI components, but
+     * calling the corresponding methods (e.g. {@link
+     * androidx.media2.session.MediaController#play()}, {@link
+     * androidx.media2.session.MediaController#pause()}) will work as well.
      *
      * @param controller the controller
      * @see #setPlayer
      */
-    public void setMediaController(@NonNull MediaController controller) {
+    public void setMediaController(@NonNull androidx.media2.session.MediaController controller) {
         if (controller == null) {
             throw new NullPointerException("controller must not be null");
         }
@@ -340,7 +353,7 @@
         setMediaControllerInternal(controller);
     }
 
-    void setMediaControllerInternal(@NonNull MediaController controller) {
+    void setMediaControllerInternal(@NonNull androidx.media2.session.MediaController controller) {
         if (mPlayer != null) {
             mPlayer.detachCallback();
         }
@@ -352,22 +365,22 @@
     }
 
     /**
-     * Sets {@link SessionPlayer} to control playback with this view.
-     * Setting a SessionPlayer will unset any MediaController or SessionPlayer
-     * that was previously set.
-     * <p>
-     * It will throw {@link IllegalStateException} if this MediaControlView belongs to
-     * a {@link VideoView} by {@link androidx.media2.widget.R.attr#enableControlView} or
-     * by {@link VideoView#setMediaControlView}. Use {@link VideoView#setPlayer} instead.
-     * <p>
-     * Note that MediaControlView allows controlling playback through its UI components, but calling
-     * the corresponding methods (e.g. {@link SessionPlayer#play()}, {@link SessionPlayer#pause()})
-     * will work as well.
+     * Sets {@link androidx.media2.common.SessionPlayer} to control playback with this view. Setting
+     * a androidx.media2.common.SessionPlayer will unset any androidx.media2.session.MediaController
+     * or androidx.media2.common.SessionPlayer that was previously set.
+     *
+     * <p>It will throw {@link IllegalStateException} if this MediaControlView belongs to a {@link
+     * VideoView} by {@link androidx.media2.widget.R.attr#enableControlView} or by {@link
+     * VideoView#setMediaControlView}. Use {@link VideoView#setPlayer} instead.
+     *
+     * <p>Note that MediaControlView allows controlling playback through its UI components, but
+     * calling the corresponding methods (e.g. {@link androidx.media2.common.SessionPlayer#play()},
+     * {@link androidx.media2.common.SessionPlayer#pause()}) will work as well.
      *
      * @param player the player
      * @see #setMediaController
      */
-    public void setPlayer(@NonNull SessionPlayer player) {
+    public void setPlayer(@NonNull androidx.media2.common.SessionPlayer player) {
         if (player == null) {
             throw new NullPointerException("player must not be null");
         }
@@ -377,7 +390,7 @@
         setPlayerInternal(player);
     }
 
-    void setPlayerInternal(@NonNull SessionPlayer player) {
+    void setPlayerInternal(@NonNull androidx.media2.common.SessionPlayer player) {
         if (mPlayer != null) {
             mPlayer.detachCallback();
         }
@@ -418,7 +431,11 @@
     /**
      * Interface definition of a callback to be invoked to inform the fullscreen mode is changed.
      * Application should handle the fullscreen mode accordingly.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public interface OnFullScreenListener {
         /**
          * Called to indicate a fullscreen mode change.
@@ -1392,7 +1409,7 @@
                 }
             };
 
-    void updateTimeViews(MediaItem item) {
+    void updateTimeViews(androidx.media2.common.MediaItem item) {
         if (item == null) {
             mProgress.setProgress(0);
             mCurrentTime.setText(mResources.getString(R.string.MediaControlView_time_placeholder));
@@ -1409,7 +1426,7 @@
         }
     }
 
-    void updateTitleView(MediaItem item) {
+    void updateTitleView(androidx.media2.common.MediaItem item) {
         if (item == null) {
             mTitleView.setText(null);
             return;
@@ -1578,13 +1595,13 @@
     boolean isCurrentMediaItemFromNetwork() {
         ensurePlayerIsNotNull();
 
-        MediaItem currentMediaItem = mPlayer.getCurrentMediaItem();
+        androidx.media2.common.MediaItem currentMediaItem = mPlayer.getCurrentMediaItem();
 
-        if (!(currentMediaItem instanceof UriMediaItem)) {
+        if (!(currentMediaItem instanceof androidx.media2.common.UriMediaItem)) {
             return false;
         }
 
-        Uri uri = ((UriMediaItem) currentMediaItem).getUri();
+        Uri uri = ((androidx.media2.common.UriMediaItem) currentMediaItem).getUri();
         return UriUtil.isFromNetwork(uri);
     }
 
@@ -1716,7 +1733,7 @@
             int sizeType = mTransportControlsMap.keyAt(i);
             View prevButton = findControlButton(sizeType, R.id.prev);
             if (prevButton != null) {
-                if (prevIndex > SessionPlayer.INVALID_ITEM_INDEX) {
+                if (prevIndex > androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) {
                     prevButton.setAlpha(1.0f);
                     prevButton.setEnabled(true);
                 } else {
@@ -1726,7 +1743,7 @@
             }
             View nextButton = findControlButton(sizeType, R.id.next);
             if (nextButton != null) {
-                if (nextIndex > SessionPlayer.INVALID_ITEM_INDEX) {
+                if (nextIndex > androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX) {
                     nextButton.setAlpha(1.0f);
                     nextButton.setEnabled(true);
                 } else {
@@ -1740,8 +1757,10 @@
     boolean shouldNotHideBars() {
         return (isCurrentItemMusic() && mSizeType == SIZE_TYPE_FULL)
                 || mAccessibilityManager.isTouchExplorationEnabled()
-                || mPlayer.getPlayerState() == SessionPlayer.PLAYER_STATE_ERROR
-                || mPlayer.getPlayerState() == SessionPlayer.PLAYER_STATE_IDLE;
+                || mPlayer.getPlayerState()
+                        == androidx.media2.common.SessionPlayer.PLAYER_STATE_ERROR
+                || mPlayer.getPlayerState()
+                        == androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
     }
 
     void seekTo(long newPosition, boolean shouldSeekNow) {
@@ -1850,7 +1869,8 @@
         }
     }
 
-    void updateTracks(PlayerWrapper player, List<TrackInfo> trackInfos) {
+    void updateTracks(
+            PlayerWrapper player, List<androidx.media2.common.SessionPlayer.TrackInfo> trackInfos) {
         // Update video track count, audio & subtitle track lists.
         mVideoTrackCount = 0;
         mAudioTracks = new ArrayList<>();
@@ -1858,18 +1878,25 @@
         mSelectedAudioTrackIndex = 0;
         // Default is -1 since subtitle selection always includes "Off" item
         mSelectedSubtitleTrackIndex = -1;
-        TrackInfo audioTrack = player.getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_AUDIO);
-        TrackInfo subtitleTrack = player.getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE);
+        androidx.media2.common.SessionPlayer.TrackInfo audioTrack =
+                player.getSelectedTrack(
+                        androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO);
+        androidx.media2.common.SessionPlayer.TrackInfo subtitleTrack =
+                player.getSelectedTrack(
+                        androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE);
         for (int i = 0; i < trackInfos.size(); i++) {
             int trackType = trackInfos.get(i).getTrackType();
-            if (trackType == TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
+            if (trackType
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
                 mVideoTrackCount++;
-            } else if (trackType == TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
+            } else if (trackType
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
                 if (trackInfos.get(i).equals(audioTrack)) {
                     mSelectedAudioTrackIndex = mAudioTracks.size();
                 }
                 mAudioTracks.add(trackInfos.get(i));
-            } else if (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+            } else if (trackType
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
                 if (trackInfos.get(i).equals(subtitleTrack)) {
                     mSelectedSubtitleTrackIndex = mSubtitleTracks.size();
                 }
@@ -1919,7 +1946,7 @@
         if (mVideoTrackCount > 0) {
             return true;
         }
-        VideoSize videoSize = mPlayer.getVideoSize();
+        androidx.media2.common.VideoSize videoSize = mPlayer.getVideoSize();
         if (videoSize.getHeight() > 0 && videoSize.getWidth() > 0) {
             Log.w(TAG, "video track count is zero, but it renders video. size: " + videoSize);
             return true;
@@ -2070,20 +2097,20 @@
             //      activity is resumed.
             //   2) Need to handle case where the media file reaches end of duration.
             switch (state) {
-                case SessionPlayer.PLAYER_STATE_PLAYING:
+                case androidx.media2.common.SessionPlayer.PLAYER_STATE_PLAYING:
                     removeCallbacks(mUpdateProgress);
                     post(mUpdateProgress);
                     resetHideCallbacks();
                     updateReplayButton(false);
                     break;
-                case SessionPlayer.PLAYER_STATE_PAUSED:
+                case androidx.media2.common.SessionPlayer.PLAYER_STATE_PAUSED:
                     updatePlayButton(PLAY_BUTTON_PLAY);
                     removeCallbacks(mUpdateProgress);
                     removeCallbacks(mHideMainBars);
                     removeCallbacks(mHideProgressBar);
                     post(mShowAllBars);
                     break;
-                case SessionPlayer.PLAYER_STATE_ERROR:
+                case androidx.media2.common.SessionPlayer.PLAYER_STATE_ERROR:
                     updatePlayButton(PLAY_BUTTON_PLAY);
                     removeCallbacks(mUpdateProgress);
                     if (getWindowToken() != null) {
@@ -2139,8 +2166,9 @@
         }
 
         @Override
-        public void onCurrentMediaItemChanged(@NonNull PlayerWrapper player,
-                @Nullable MediaItem mediaItem) {
+        public void onCurrentMediaItemChanged(
+                @NonNull PlayerWrapper player,
+                @Nullable androidx.media2.common.MediaItem mediaItem) {
             if (player != mPlayer) return;
 
             if (DEBUG) {
@@ -2153,8 +2181,10 @@
         }
 
         @Override
-        void onPlaylistChanged(@NonNull PlayerWrapper player, @Nullable List<MediaItem> list,
-                @Nullable MediaMetadata metadata) {
+        void onPlaylistChanged(
+                @NonNull PlayerWrapper player,
+                @Nullable List<androidx.media2.common.MediaItem> list,
+                @Nullable androidx.media2.common.MediaMetadata metadata) {
             if (player != mPlayer) return;
 
             if (DEBUG) {
@@ -2178,8 +2208,9 @@
         }
 
         @Override
-        public void onAllowedCommandsChanged(@NonNull PlayerWrapper player,
-                @NonNull SessionCommandGroup commands) {
+        public void onAllowedCommandsChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.session.SessionCommandGroup commands) {
             if (player != mPlayer) return;
 
             updateAllowedCommands();
@@ -2231,11 +2262,13 @@
         }
 
         @Override
-        void onTracksChanged(@NonNull PlayerWrapper player, @NonNull List<TrackInfo> tracks) {
+        void onTracksChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull List<androidx.media2.common.SessionPlayer.TrackInfo> tracks) {
             if (player != mPlayer) return;
 
             if (DEBUG) {
-                Log.d(TAG, "onTrackInfoChanged(): " + tracks);
+                Log.d(TAG, "onandroidx.media2.common.SessionPlayer.TrackInfoChanged(): " + tracks);
             }
 
             updateTracks(player, tracks);
@@ -2244,13 +2277,16 @@
         }
 
         @Override
-        void onTrackSelected(@NonNull PlayerWrapper player, @NonNull TrackInfo trackInfo) {
+        void onTrackSelected(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             if (player != mPlayer) return;
 
             if (DEBUG) {
                 Log.d(TAG, "onTrackSelected(): " + trackInfo);
             }
-            if (trackInfo.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+            if (trackInfo.getTrackType()
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
                 for (int i = 0; i < mSubtitleTracks.size(); i++) {
                     if (mSubtitleTracks.get(i).equals(trackInfo)) {
                         mSelectedSubtitleTrackIndex = i;
@@ -2265,7 +2301,8 @@
                         break;
                     }
                 }
-            } else if (trackInfo.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
+            } else if (trackInfo.getTrackType()
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
                 for (int i = 0; i < mAudioTracks.size(); i++) {
                     if (mAudioTracks.get(i).equals(trackInfo)) {
                         mSelectedAudioTrackIndex = i;
@@ -2279,13 +2316,16 @@
         }
 
         @Override
-        void onTrackDeselected(@NonNull PlayerWrapper player, @NonNull TrackInfo trackInfo) {
+        void onTrackDeselected(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             if (player != mPlayer) return;
 
             if (DEBUG) {
                 Log.d(TAG, "onTrackDeselected(): " + trackInfo);
             }
-            if (trackInfo.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+            if (trackInfo.getTrackType()
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
                 for (int i = 0; i < mSubtitleTracks.size(); i++) {
                     if (mSubtitleTracks.get(i).equals(trackInfo)) {
                         mSelectedSubtitleTrackIndex = -1;
@@ -2304,14 +2344,16 @@
         }
 
         @Override
-        void onVideoSizeChanged(@NonNull PlayerWrapper player, @NonNull VideoSize videoSize) {
+        void onVideoSizeChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.VideoSize videoSize) {
             if (player != mPlayer) return;
 
             if (DEBUG) {
                 Log.d(TAG, "onVideoSizeChanged(): " + videoSize);
             }
             if (mVideoTrackCount == 0 && videoSize.getHeight() > 0 && videoSize.getWidth() > 0) {
-                List<TrackInfo> tracks = player.getTracks();
+                List<androidx.media2.common.SessionPlayer.TrackInfo> tracks = player.getTracks();
                 if (tracks != null) {
                     updateTracks(player, tracks);
                 }
diff --git a/media2/media2-widget/src/main/java/androidx/media2/widget/PlayerWrapper.java b/media2/media2-widget/src/main/java/androidx/media2/widget/PlayerWrapper.java
index fdbbced..575f96f 100644
--- a/media2/media2-widget/src/main/java/androidx/media2/widget/PlayerWrapper.java
+++ b/media2/media2-widget/src/main/java/androidx/media2/widget/PlayerWrapper.java
@@ -21,16 +21,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.core.util.ObjectsCompat;
-import androidx.media2.common.BaseResult;
-import androidx.media2.common.MediaItem;
-import androidx.media2.common.MediaMetadata;
-import androidx.media2.common.SessionPlayer;
-import androidx.media2.common.SessionPlayer.TrackInfo;
-import androidx.media2.common.SubtitleData;
-import androidx.media2.common.VideoSize;
-import androidx.media2.session.MediaController;
-import androidx.media2.session.SessionCommand;
-import androidx.media2.session.SessionCommandGroup;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -38,12 +28,11 @@
 import java.util.List;
 import java.util.concurrent.Executor;
 
-/**
- * Wrapper for MediaController and SessionPlayer
- */
+/** Wrapper for androidx.media2.session.MediaController and androidx.media2.common.SessionPlayer */
+@SuppressWarnings("deprecation")
 class PlayerWrapper {
-    final MediaController mController;
-    final SessionPlayer mPlayer;
+    final androidx.media2.session.MediaController mController;
+    final androidx.media2.common.SessionPlayer mPlayer;
 
     private final Executor mCallbackExecutor;
 
@@ -56,15 +45,19 @@
 
     // cached states
     @SuppressWarnings("WeakerAccess") /* synthetic access */
-    int mSavedPlayerState = SessionPlayer.PLAYER_STATE_IDLE;
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    SessionCommandGroup mAllowedCommands;
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    MediaMetadata mMediaMetadata;
+    int mSavedPlayerState = androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
 
-    private final SessionCommandGroup mAllCommands;
+    @SuppressWarnings("WeakerAccess") /* synthetic access */
+    androidx.media2.session.SessionCommandGroup mAllowedCommands;
 
-    PlayerWrapper(@NonNull MediaController controller, @NonNull Executor executor,
+    @SuppressWarnings("WeakerAccess") /* synthetic access */
+    androidx.media2.common.MediaMetadata mMediaMetadata;
+
+    private final androidx.media2.session.SessionCommandGroup mAllCommands;
+
+    PlayerWrapper(
+            @NonNull androidx.media2.session.MediaController controller,
+            @NonNull Executor executor,
             @NonNull PlayerCallback callback) {
         if (controller == null) throw new NullPointerException("controller must not be null");
         if (executor == null) throw new NullPointerException("executor must not be null");
@@ -80,7 +73,9 @@
         mAllCommands = null;
     }
 
-    PlayerWrapper(@NonNull SessionPlayer player, @NonNull Executor executor,
+    PlayerWrapper(
+            @NonNull androidx.media2.common.SessionPlayer player,
+            @NonNull Executor executor,
             @NonNull PlayerCallback callback) {
         if (player == null) throw new NullPointerException("player must not be null");
         if (executor == null) throw new NullPointerException("executor must not be null");
@@ -93,9 +88,11 @@
         mController = null;
         mControllerCallback = null;
 
-        mAllCommands = new SessionCommandGroup.Builder()
-                .addAllPredefinedCommands(SessionCommand.COMMAND_VERSION_1)
-                .build();
+        mAllCommands =
+                new androidx.media2.session.SessionCommandGroup.Builder()
+                        .addAllPredefinedCommands(
+                                androidx.media2.session.SessionCommand.COMMAND_VERSION_1)
+                        .build();
     }
 
     boolean hasDisconnectedController() {
@@ -124,11 +121,11 @@
     }
 
     boolean isPlaying() {
-        return mSavedPlayerState == SessionPlayer.PLAYER_STATE_PLAYING;
+        return mSavedPlayerState == androidx.media2.common.SessionPlayer.PLAYER_STATE_PLAYING;
     }
 
     long getCurrentPosition() {
-        if (mSavedPlayerState == SessionPlayer.PLAYER_STATE_IDLE) {
+        if (mSavedPlayerState == androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE) {
             return 0;
         }
         long position = 0;
@@ -141,7 +138,7 @@
     }
 
     long getBufferPercentage() {
-        if (mSavedPlayerState == SessionPlayer.PLAYER_STATE_IDLE) {
+        if (mSavedPlayerState == androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE) {
             return 0;
         }
         long duration = getDurationMs();
@@ -161,43 +158,53 @@
         } else if (mPlayer != null) {
             return mPlayer.getPlayerState();
         }
-        return SessionPlayer.PLAYER_STATE_IDLE;
+        return androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
     }
 
     boolean canPause() {
-        return mAllowedCommands != null && mAllowedCommands.hasCommand(
-                SessionCommand.COMMAND_CODE_PLAYER_PAUSE);
+        return mAllowedCommands != null
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand.COMMAND_CODE_PLAYER_PAUSE);
     }
 
     boolean canSeekBackward() {
-        return mAllowedCommands != null && mAllowedCommands.hasCommand(
-                SessionCommand.COMMAND_CODE_SESSION_REWIND);
+        return mAllowedCommands != null
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand.COMMAND_CODE_SESSION_REWIND);
     }
 
     boolean canSeekForward() {
-        return mAllowedCommands != null && mAllowedCommands.hasCommand(
-                SessionCommand.COMMAND_CODE_SESSION_FAST_FORWARD);
+        return mAllowedCommands != null
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand.COMMAND_CODE_SESSION_FAST_FORWARD);
     }
 
     boolean canSkipToNext() {
-        return mAllowedCommands != null && mAllowedCommands.hasCommand(
-                SessionCommand.COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM);
+        return mAllowedCommands != null
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand
+                                .COMMAND_CODE_PLAYER_SKIP_TO_NEXT_PLAYLIST_ITEM);
     }
 
     boolean canSkipToPrevious() {
-        return mAllowedCommands != null && mAllowedCommands.hasCommand(
-                SessionCommand.COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM);
+        return mAllowedCommands != null
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand
+                                .COMMAND_CODE_PLAYER_SKIP_TO_PREVIOUS_PLAYLIST_ITEM);
     }
 
     boolean canSeekTo() {
-        return mAllowedCommands != null && mAllowedCommands.hasCommand(
-                SessionCommand.COMMAND_CODE_PLAYER_SEEK_TO);
+        return mAllowedCommands != null
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand.COMMAND_CODE_PLAYER_SEEK_TO);
     }
 
     boolean canSelectDeselectTrack() {
         return mAllowedCommands != null
-                && mAllowedCommands.hasCommand(SessionCommand.COMMAND_CODE_PLAYER_SELECT_TRACK)
-                && mAllowedCommands.hasCommand(SessionCommand.COMMAND_CODE_PLAYER_DESELECT_TRACK);
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand.COMMAND_CODE_PLAYER_SELECT_TRACK)
+                && mAllowedCommands.hasCommand(
+                        androidx.media2.session.SessionCommand.COMMAND_CODE_PLAYER_DESELECT_TRACK);
     }
 
     @SuppressWarnings("FutureReturnValueIgnored")
@@ -264,7 +271,7 @@
     }
 
     @SuppressWarnings("FutureReturnValueIgnored")
-    void selectTrack(TrackInfo trackInfo) {
+    void selectTrack(androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
         if (mController != null) {
             mController.selectTrack(trackInfo);
         } else if (mPlayer != null) {
@@ -273,7 +280,7 @@
     }
 
     @SuppressWarnings("FutureReturnValueIgnored")
-    void deselectTrack(TrackInfo trackInfo) {
+    void deselectTrack(androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
         if (mController != null) {
             mController.deselectTrack(trackInfo);
         } else if (mPlayer != null) {
@@ -282,7 +289,7 @@
     }
 
     long getDurationMs() {
-        if (mSavedPlayerState == SessionPlayer.PLAYER_STATE_IDLE) {
+        if (mSavedPlayerState == androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE) {
             return 0;
         }
         long duration = 0;
@@ -296,8 +303,10 @@
 
     CharSequence getTitle() {
         if (mMediaMetadata != null) {
-            if (mMediaMetadata.containsKey(MediaMetadata.METADATA_KEY_TITLE)) {
-                return mMediaMetadata.getText(MediaMetadata.METADATA_KEY_TITLE);
+            if (mMediaMetadata.containsKey(
+                    androidx.media2.common.MediaMetadata.METADATA_KEY_TITLE)) {
+                return mMediaMetadata.getText(
+                        androidx.media2.common.MediaMetadata.METADATA_KEY_TITLE);
             }
         }
         return null;
@@ -305,15 +314,17 @@
 
     CharSequence getArtistText() {
         if (mMediaMetadata != null) {
-            if (mMediaMetadata.containsKey(MediaMetadata.METADATA_KEY_ARTIST)) {
-                return mMediaMetadata.getText(MediaMetadata.METADATA_KEY_ARTIST);
+            if (mMediaMetadata.containsKey(
+                    androidx.media2.common.MediaMetadata.METADATA_KEY_ARTIST)) {
+                return mMediaMetadata.getText(
+                        androidx.media2.common.MediaMetadata.METADATA_KEY_ARTIST);
             }
         }
         return null;
     }
 
     @Nullable
-    MediaItem getCurrentMediaItem() {
+    androidx.media2.common.MediaItem getCurrentMediaItem() {
         if (mController != null) {
             return mController.getCurrentMediaItem();
         } else if (mPlayer != null) {
@@ -323,7 +334,7 @@
     }
 
     @Nullable
-    private SessionCommandGroup getAllowedCommands() {
+    private androidx.media2.session.SessionCommandGroup getAllowedCommands() {
         if (mController != null) {
             return mController.getAllowedCommands();
         } else if (mPlayer != null) {
@@ -343,13 +354,13 @@
         }
 
         boolean allowedCommandsChanged = false;
-        SessionCommandGroup allowedCommands = getAllowedCommands();
+        androidx.media2.session.SessionCommandGroup allowedCommands = getAllowedCommands();
         if (!ObjectsCompat.equals(mAllowedCommands, allowedCommands)) {
             mAllowedCommands = allowedCommands;
             allowedCommandsChanged = true;
         }
 
-        MediaItem item = getCurrentMediaItem();
+        androidx.media2.common.MediaItem item = getCurrentMediaItem();
         mMediaMetadata = item == null ? null : item.getMetadata();
 
         if (playerStateChanged) {
@@ -363,17 +374,17 @@
     }
 
     @NonNull
-    VideoSize getVideoSize() {
+    androidx.media2.common.VideoSize getVideoSize() {
         if (mController != null) {
             return mController.getVideoSize();
         } else if (mPlayer != null) {
             return mPlayer.getVideoSize();
         }
-        return new VideoSize(0, 0);
+        return new androidx.media2.common.VideoSize(0, 0);
     }
 
     @NonNull
-    List<TrackInfo> getTracks() {
+    List<androidx.media2.common.SessionPlayer.TrackInfo> getTracks() {
         if (mController != null) {
             return mController.getTracks();
         } else if (mPlayer != null) {
@@ -383,7 +394,7 @@
     }
 
     @Nullable
-    TrackInfo getSelectedTrack(int trackType) {
+    androidx.media2.common.SessionPlayer.TrackInfo getSelectedTrack(int trackType) {
         if (mController != null) {
             return mController.getSelectedTrack(trackType);
         } else if (mPlayer != null) {
@@ -392,7 +403,7 @@
         return null;
     }
 
-    ListenableFuture<? extends BaseResult> setSurface(Surface surface) {
+    ListenableFuture<? extends androidx.media2.common.BaseResult> setSurface(Surface surface) {
         if (mController != null) {
             return mController.setSurface(surface);
         } else if (mPlayer != null) {
@@ -407,7 +418,7 @@
         } else if (mPlayer != null) {
             return mPlayer.getCurrentMediaItemIndex();
         }
-        return SessionPlayer.INVALID_ITEM_INDEX;
+        return androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX;
     }
 
     int getPreviousMediaItemIndex() {
@@ -416,7 +427,7 @@
         } else if (mPlayer != null) {
             return mPlayer.getPreviousMediaItemIndex();
         }
-        return SessionPlayer.INVALID_ITEM_INDEX;
+        return androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX;
     }
 
     int getNextMediaItemIndex() {
@@ -425,90 +436,107 @@
         } else if (mPlayer != null) {
             return mPlayer.getNextMediaItemIndex();
         }
-        return SessionPlayer.INVALID_ITEM_INDEX;
+        return androidx.media2.common.SessionPlayer.INVALID_ITEM_INDEX;
     }
 
-    private class MediaControllerCallback extends MediaController.ControllerCallback {
+    private class MediaControllerCallback
+            extends androidx.media2.session.MediaController.ControllerCallback {
         MediaControllerCallback() {
         }
 
         @Override
-        public void onConnected(@NonNull MediaController controller,
-                @NonNull SessionCommandGroup allowedCommands) {
+        public void onConnected(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull androidx.media2.session.SessionCommandGroup allowedCommands) {
             mWrapperCallback.onConnected(PlayerWrapper.this);
             updateAndNotifyCachedStates();
         }
 
         @Override
-        public void onAllowedCommandsChanged(@NonNull MediaController controller,
-                @NonNull SessionCommandGroup commands) {
+        public void onAllowedCommandsChanged(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull androidx.media2.session.SessionCommandGroup commands) {
             if (ObjectsCompat.equals(mAllowedCommands, commands)) return;
             mAllowedCommands = commands;
             mWrapperCallback.onAllowedCommandsChanged(PlayerWrapper.this, commands);
         }
 
         @Override
-        public void onPlayerStateChanged(@NonNull MediaController controller, int state) {
+        public void onPlayerStateChanged(
+                @NonNull androidx.media2.session.MediaController controller, int state) {
             if (mSavedPlayerState == state) return;
             mSavedPlayerState = state;
             mWrapperCallback.onPlayerStateChanged(PlayerWrapper.this, state);
         }
 
         @Override
-        public void onPlaybackSpeedChanged(@NonNull MediaController controller, float speed) {
+        public void onPlaybackSpeedChanged(
+                @NonNull androidx.media2.session.MediaController controller, float speed) {
             mWrapperCallback.onPlaybackSpeedChanged(PlayerWrapper.this, speed);
         }
 
         @Override
-        public void onSeekCompleted(@NonNull MediaController controller, long position) {
+        public void onSeekCompleted(
+                @NonNull androidx.media2.session.MediaController controller, long position) {
             mWrapperCallback.onSeekCompleted(PlayerWrapper.this, position);
         }
 
         @Override
-        public void onCurrentMediaItemChanged(@NonNull MediaController controller,
-                @Nullable MediaItem item) {
+        public void onCurrentMediaItemChanged(
+                @NonNull androidx.media2.session.MediaController controller,
+                @Nullable androidx.media2.common.MediaItem item) {
             mMediaMetadata = item == null ? null : item.getMetadata();
             mWrapperCallback.onCurrentMediaItemChanged(PlayerWrapper.this, item);
         }
 
         @Override
-        public void onPlaylistChanged(@NonNull MediaController controller,
-                @Nullable List<MediaItem> list, @Nullable MediaMetadata metadata) {
+        public void onPlaylistChanged(
+                @NonNull androidx.media2.session.MediaController controller,
+                @Nullable List<androidx.media2.common.MediaItem> list,
+                @Nullable androidx.media2.common.MediaMetadata metadata) {
             mWrapperCallback.onPlaylistChanged(PlayerWrapper.this, list, metadata);
         }
 
         @Override
-        public void onPlaybackCompleted(@NonNull MediaController controller) {
+        public void onPlaybackCompleted(
+                @NonNull androidx.media2.session.MediaController controller) {
             mWrapperCallback.onPlaybackCompleted(PlayerWrapper.this);
         }
 
         @Override
-        public void onVideoSizeChanged(@NonNull MediaController controller,
-                @NonNull VideoSize videoSize) {
+        public void onVideoSizeChanged(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull androidx.media2.common.VideoSize videoSize) {
             mWrapperCallback.onVideoSizeChanged(PlayerWrapper.this, videoSize);
         }
 
         @Override
-        public void onSubtitleData(@NonNull MediaController controller, @NonNull MediaItem item,
-                @NonNull TrackInfo track, @NonNull SubtitleData data) {
+        public void onSubtitleData(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull androidx.media2.common.MediaItem item,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo track,
+                @NonNull androidx.media2.common.SubtitleData data) {
             mWrapperCallback.onSubtitleData(PlayerWrapper.this, item, track, data);
         }
 
         @Override
-        public void onTracksChanged(@NonNull MediaController controller,
-                @NonNull List<TrackInfo> tracks) {
+        public void onTracksChanged(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull List<androidx.media2.common.SessionPlayer.TrackInfo> tracks) {
             mWrapperCallback.onTracksChanged(PlayerWrapper.this, tracks);
         }
 
         @Override
-        public void onTrackSelected(@NonNull MediaController controller,
-                @NonNull TrackInfo trackInfo) {
+        public void onTrackSelected(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             mWrapperCallback.onTrackSelected(PlayerWrapper.this, trackInfo);
         }
 
         @Override
-        public void onTrackDeselected(@NonNull MediaController controller,
-                @NonNull TrackInfo trackInfo) {
+        public void onTrackDeselected(
+                @NonNull androidx.media2.session.MediaController controller,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             mWrapperCallback.onTrackDeselected(PlayerWrapper.this, trackInfo);
         }
     }
@@ -516,79 +544,96 @@
     private void notifyNonCachedStates() {
         mWrapperCallback.onPlaybackSpeedChanged(this, getPlaybackSpeed());
 
-        List<TrackInfo> trackInfos = getTracks();
+        List<androidx.media2.common.SessionPlayer.TrackInfo> trackInfos = getTracks();
         if (trackInfos != null) {
             mWrapperCallback.onTracksChanged(PlayerWrapper.this, trackInfos);
         }
-        MediaItem item = getCurrentMediaItem();
+        androidx.media2.common.MediaItem item = getCurrentMediaItem();
         if (item != null) {
             mWrapperCallback.onVideoSizeChanged(PlayerWrapper.this, getVideoSize());
         }
     }
 
-    private class SessionPlayerCallback extends SessionPlayer.PlayerCallback {
+    private class SessionPlayerCallback
+            extends androidx.media2.common.SessionPlayer.PlayerCallback {
         SessionPlayerCallback() {
         }
 
         @Override
-        public void onPlayerStateChanged(@NonNull SessionPlayer player, int playerState) {
+        public void onPlayerStateChanged(
+                @NonNull androidx.media2.common.SessionPlayer player, int playerState) {
             if (mSavedPlayerState == playerState) return;
             mSavedPlayerState = playerState;
             mWrapperCallback.onPlayerStateChanged(PlayerWrapper.this, playerState);
         }
 
         @Override
-        public void onPlaybackSpeedChanged(@NonNull SessionPlayer player, float playbackSpeed) {
+        public void onPlaybackSpeedChanged(
+                @NonNull androidx.media2.common.SessionPlayer player, float playbackSpeed) {
             mWrapperCallback.onPlaybackSpeedChanged(PlayerWrapper.this, playbackSpeed);
         }
 
         @Override
-        public void onSeekCompleted(@NonNull SessionPlayer player, long position) {
+        public void onSeekCompleted(
+                @NonNull androidx.media2.common.SessionPlayer player, long position) {
             mWrapperCallback.onSeekCompleted(PlayerWrapper.this, position);
         }
 
         @Override
-        public void onCurrentMediaItemChanged(@NonNull SessionPlayer player,
-                @NonNull MediaItem item) {
+        public void onCurrentMediaItemChanged(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @NonNull androidx.media2.common.MediaItem item) {
             mMediaMetadata = item == null ? null : item.getMetadata();
             mWrapperCallback.onCurrentMediaItemChanged(PlayerWrapper.this, item);
         }
 
         @Override
-        public void onPlaylistChanged(@NonNull SessionPlayer player, @Nullable List<MediaItem> list,
-                @Nullable MediaMetadata metadata) {
+        public void onPlaylistChanged(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @Nullable List<androidx.media2.common.MediaItem> list,
+                @Nullable androidx.media2.common.MediaMetadata metadata) {
             mWrapperCallback.onPlaylistChanged(PlayerWrapper.this, list, metadata);
         }
 
         @Override
-        public void onPlaybackCompleted(@NonNull SessionPlayer player) {
+        public void onPlaybackCompleted(@NonNull androidx.media2.common.SessionPlayer player) {
             mWrapperCallback.onPlaybackCompleted(PlayerWrapper.this);
         }
 
         @Override
-        public void onVideoSizeChanged(@NonNull SessionPlayer player, @NonNull VideoSize size) {
+        public void onVideoSizeChanged(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @NonNull androidx.media2.common.VideoSize size) {
             mWrapperCallback.onVideoSizeChanged(PlayerWrapper.this, size);
         }
 
         @Override
-        public void onSubtitleData(@NonNull SessionPlayer player, @NonNull MediaItem item,
-                @NonNull TrackInfo track, @NonNull SubtitleData data) {
+        public void onSubtitleData(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @NonNull androidx.media2.common.MediaItem item,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo track,
+                @NonNull androidx.media2.common.SubtitleData data) {
             mWrapperCallback.onSubtitleData(PlayerWrapper.this, item, track, data);
         }
 
         @Override
-        public void onTracksChanged(@NonNull SessionPlayer player,
-                @NonNull List<TrackInfo> tracks) {
+        public void onTracksChanged(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @NonNull List<androidx.media2.common.SessionPlayer.TrackInfo> tracks) {
             mWrapperCallback.onTracksChanged(PlayerWrapper.this, tracks);
         }
 
         @Override
-        public void onTrackSelected(@NonNull SessionPlayer player, @NonNull TrackInfo trackInfo) {
+        public void onTrackSelected(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             mWrapperCallback.onTrackSelected(PlayerWrapper.this, trackInfo);
         }
 
         @Override
-        public void onTrackDeselected(@NonNull SessionPlayer player, @NonNull TrackInfo trackInfo) {
+        public void onTrackDeselected(
+                @NonNull androidx.media2.common.SessionPlayer player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             mWrapperCallback.onTrackDeselected(PlayerWrapper.this, trackInfo);
         }
     }
@@ -596,14 +641,19 @@
     abstract static class PlayerCallback {
         void onConnected(@NonNull PlayerWrapper player) {
         }
-        void onAllowedCommandsChanged(@NonNull PlayerWrapper player,
-                @NonNull SessionCommandGroup commands) {
-        }
-        void onCurrentMediaItemChanged(@NonNull PlayerWrapper player, @Nullable MediaItem item) {
-        }
-        void onPlaylistChanged(@NonNull PlayerWrapper player, @Nullable List<MediaItem> list,
-                @Nullable MediaMetadata metadata) {
-        }
+
+        void onAllowedCommandsChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.session.SessionCommandGroup commands) {}
+
+        void onCurrentMediaItemChanged(
+                @NonNull PlayerWrapper player, @Nullable androidx.media2.common.MediaItem item) {}
+
+        void onPlaylistChanged(
+                @NonNull PlayerWrapper player,
+                @Nullable List<androidx.media2.common.MediaItem> list,
+                @Nullable androidx.media2.common.MediaMetadata metadata) {}
+
         void onPlayerStateChanged(@NonNull PlayerWrapper player, int state) {
         }
         void onPlaybackSpeedChanged(@NonNull PlayerWrapper player, float speed) {
@@ -612,16 +662,27 @@
         }
         void onPlaybackCompleted(@NonNull PlayerWrapper player) {
         }
-        void onVideoSizeChanged(@NonNull PlayerWrapper player, @NonNull VideoSize videoSize) {
-        }
-        void onTracksChanged(@NonNull PlayerWrapper player, @NonNull List<TrackInfo> tracks) {
-        }
-        void onTrackSelected(@NonNull PlayerWrapper player, @NonNull TrackInfo trackInfo) {
-        }
-        void onTrackDeselected(@NonNull PlayerWrapper player, @NonNull TrackInfo trackInfo) {
-        }
-        void onSubtitleData(@NonNull PlayerWrapper player, @NonNull MediaItem item,
-                @NonNull TrackInfo track, @NonNull SubtitleData data) {
-        }
+
+        void onVideoSizeChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.VideoSize videoSize) {}
+
+        void onTracksChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull List<androidx.media2.common.SessionPlayer.TrackInfo> tracks) {}
+
+        void onTrackSelected(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {}
+
+        void onTrackDeselected(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {}
+
+        void onSubtitleData(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.MediaItem item,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo track,
+                @NonNull androidx.media2.common.SubtitleData data) {}
     }
 }
diff --git a/media2/media2-widget/src/main/java/androidx/media2/widget/SubtitleTrack.java b/media2/media2-widget/src/main/java/androidx/media2/widget/SubtitleTrack.java
index c7cc04b..377e7003 100644
--- a/media2/media2-widget/src/main/java/androidx/media2/widget/SubtitleTrack.java
+++ b/media2/media2-widget/src/main/java/androidx/media2/widget/SubtitleTrack.java
@@ -26,7 +26,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.media2.common.SubtitleData;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -36,9 +35,10 @@
 
 // Note: This is forked from android.media.SubtitleTrack since P
 /**
- * A subtitle track abstract base class that is responsible for parsing and displaying
- * an instance of a particular type of subtitle.
+ * A subtitle track abstract base class that is responsible for parsing and displaying an instance
+ * of a particular type of subtitle.
  */
+@SuppressWarnings("deprecation")
 abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeListener {
     private static final String TAG = "SubtitleTrack";
     private long mLastUpdateTimeMs;
@@ -75,10 +75,8 @@
 
     private long mNextScheduledTimeMs = -1;
 
-    /**
-     * Called when there is input data for the subtitle track.
-     */
-    public void onData(SubtitleData data) {
+    /** Called when there is input data for the subtitle track. */
+    public void onData(androidx.media2.common.SubtitleData data) {
         long runID = data.getStartTimeUs() + 1;
         onData(data.getData(), true /* eos */, runID);
         setRunDiscardTimeMs(
diff --git a/media2/media2-widget/src/main/java/androidx/media2/widget/VideoSurfaceView.java b/media2/media2-widget/src/main/java/androidx/media2/widget/VideoSurfaceView.java
index f317550..ecc08de 100644
--- a/media2/media2-widget/src/main/java/androidx/media2/widget/VideoSurfaceView.java
+++ b/media2/media2-widget/src/main/java/androidx/media2/widget/VideoSurfaceView.java
@@ -16,8 +16,6 @@
 
 package androidx.media2.widget;
 
-import static androidx.media2.widget.VideoView.VIEW_TYPE_SURFACEVIEW;
-
 import android.content.Context;
 import android.graphics.Rect;
 import android.view.Surface;
@@ -26,8 +24,8 @@
 
 import androidx.core.content.ContextCompat;
 
-class VideoSurfaceView extends SurfaceView
-        implements VideoViewInterface, SurfaceHolder.Callback {
+@SuppressWarnings("deprecation")
+class VideoSurfaceView extends SurfaceView implements VideoViewInterface, SurfaceHolder.Callback {
     private Surface mSurface = null;
     SurfaceListener mSurfaceListener = null;
     private PlayerWrapper mPlayer;
@@ -67,7 +65,7 @@
 
     @Override
     public int getViewType() {
-        return VIEW_TYPE_SURFACEVIEW;
+        return androidx.media2.widget.VideoView.VIEW_TYPE_SURFACEVIEW;
     }
 
     @Override
diff --git a/media2/media2-widget/src/main/java/androidx/media2/widget/VideoTextureView.java b/media2/media2-widget/src/main/java/androidx/media2/widget/VideoTextureView.java
index 46e93b7..da63d3f 100644
--- a/media2/media2-widget/src/main/java/androidx/media2/widget/VideoTextureView.java
+++ b/media2/media2-widget/src/main/java/androidx/media2/widget/VideoTextureView.java
@@ -16,8 +16,6 @@
 
 package androidx.media2.widget;
 
-import static androidx.media2.widget.VideoView.VIEW_TYPE_TEXTUREVIEW;
-
 import android.content.Context;
 import android.graphics.SurfaceTexture;
 import android.view.Surface;
@@ -25,6 +23,7 @@
 
 import androidx.core.content.ContextCompat;
 
+@SuppressWarnings("deprecation")
 class VideoTextureView extends TextureView
         implements VideoViewInterface, TextureView.SurfaceTextureListener {
     private Surface mSurface;
@@ -68,7 +67,7 @@
 
     @Override
     public int getViewType() {
-        return VIEW_TYPE_TEXTUREVIEW;
+        return androidx.media2.widget.VideoView.VIEW_TYPE_TEXTUREVIEW;
     }
 
     @Override
diff --git a/media2/media2-widget/src/main/java/androidx/media2/widget/VideoView.java b/media2/media2-widget/src/main/java/androidx/media2/widget/VideoView.java
index 1edd489..20d4008 100644
--- a/media2/media2-widget/src/main/java/androidx/media2/widget/VideoView.java
+++ b/media2/media2-widget/src/main/java/androidx/media2/widget/VideoView.java
@@ -31,15 +31,6 @@
 import androidx.annotation.Nullable;
 import androidx.core.content.ContextCompat;
 import androidx.core.view.ViewCompat;
-import androidx.media2.common.BaseResult;
-import androidx.media2.common.MediaItem;
-import androidx.media2.common.MediaMetadata;
-import androidx.media2.common.SessionPlayer;
-import androidx.media2.common.SessionPlayer.TrackInfo;
-import androidx.media2.common.SubtitleData;
-import androidx.media2.common.VideoSize;
-import androidx.media2.session.MediaController;
-import androidx.media2.session.MediaSession;
 import androidx.palette.graphics.Palette;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -54,109 +45,129 @@
 import java.util.concurrent.TimeoutException;
 
 /**
- * A high level view for media playback that can be integrated with either a {@link SessionPlayer}
- * or a {@link MediaController}. Developers can easily implement a video rendering application
- * using this class. By default, a {@link MediaControlView} is attached so the playback
- * control buttons are displayed on top of VideoView.
- * <p>
- * Contents:
+ * A high level view for media playback that can be integrated with either a {@link
+ * androidx.media2.common.SessionPlayer} or a {@link androidx.media2.session.MediaController}.
+ * Developers can easily implement a video rendering application using this class. By default, a
+ * {@link MediaControlView} is attached so the playback control buttons are displayed on top of
+ * VideoView.
+ *
+ * <p>Contents:
+ *
  * <ol>
- *     <li><a href="UseCases">Using VideoView with SessionPlayer or MediaController</a>
- *     <li><a href="UseWithMCV">Using VideoView with MediaControlView</a>
- *     <li><a href="ViewType">Choosing a view type</a>
- *     <li><a href="LegacyVideoView">Comparison with android.widget.VideoView</a>
- *     <li><a href="DisplayMetadata">Displaying Metadata</a>
+ *   <li><a href="UseCases">Using VideoView with androidx.media2.common.SessionPlayer or
+ *       androidx.media2.session.MediaController</a>
+ *   <li><a href="UseWithMCV">Using VideoView with MediaControlView</a>
+ *   <li><a href="ViewType">Choosing a view type</a>
+ *   <li><a href="LegacyVideoView">Comparison with android.widget.VideoView</a>
+ *   <li><a href="DisplayMetadata">Displaying Metadata</a>
  * </ol>
  *
- * <h3 id="UseCases">Using VideoView with SessionPlayer or MediaController</h3>
+ * <h3 id="UseCases">Using VideoView with androidx.media2.common.SessionPlayer or
+ * androidx.media2.session.MediaController</h3>
+ *
  * <ul>
- *     <li> For simple use cases that do not require communication with a {@link MediaSession},
- *     apps need to create a player instance that extends {@link SessionPlayer} (e.g.
- *     {@link androidx.media2.player.MediaPlayer}) and link it to this view by calling
- *     {@link #setPlayer}.
- *     <li> For more advanced use cases that require a {@link MediaSession} (e.g. handling media
- *     key events, integrating with other MediaSession apps as Assistant), apps need to create
- *     a {@link MediaController} that's attached to the {@link MediaSession} and link it to this
- *     view by calling {@link #setMediaController}.
+ *   <li>For simple use cases that do not require communication with a {@link
+ *       androidx.media2.session.MediaSession}, apps need to create a player instance that extends
+ *       {@link androidx.media2.common.SessionPlayer} (e.g. {@link
+ *       androidx.media2.player.MediaPlayer}) and link it to this view by calling {@link
+ *       #setPlayer}.
+ *   <li>For more advanced use cases that require a {@link androidx.media2.session.MediaSession}
+ *       (e.g. handling media key events, integrating with other
+ *       androidx.media2.session.MediaSession apps as Assistant), apps need to create a {@link
+ *       androidx.media2.session.MediaController} that's attached to the {@link
+ *       androidx.media2.session.MediaSession} and link it to this view by calling {@link
+ *       #setMediaController}.
  * </ul>
  *
  * <h3 id="UseWithMCV">Using VideoView with MediaControlView</h3>
- * {@link VideoView} is working with {@link MediaControlView} and a MediaControlView
- * instance is attached to VideoView by default.
- * <p>
- * If you want to attach a custom {@link MediaControlView}, assign the custom media
- * control widget using {@link #setMediaControlView}.
- * <p>
- * If you don't want to use {@link MediaControlView}, set
- * the VideoView attribute {@link androidx.media2.widget.R.attr#enableControlView} to false.
+ *
+ * {@link VideoView} is working with {@link MediaControlView} and a MediaControlView instance is
+ * attached to VideoView by default.
+ *
+ * <p>If you want to attach a custom {@link MediaControlView}, assign the custom media control
+ * widget using {@link #setMediaControlView}.
+ *
+ * <p>If you don't want to use {@link MediaControlView}, set the VideoView attribute {@link
+ * androidx.media2.widget.R.attr#enableControlView} to false.
  *
  * <h3 id="ViewType">Choosing a view type</h3>
- * VideoView can render videos on a TextureView or SurfaceView. The
- * default is SurfaceView which can be changed by using the {@link #setViewType(int)} method or
- * by setting the {@link androidx.media2.widget.R.attr#viewType} attribute in the layout file.
- * <p> SurfaceView is recommended in most cases for saving battery life.
- * TextureView might be preferred for supporting various UIs such as animation and translucency.
+ *
+ * VideoView can render videos on a TextureView or SurfaceView. The default is SurfaceView which can
+ * be changed by using the {@link #setViewType(int)} method or by setting the {@link
+ * androidx.media2.widget.R.attr#viewType} attribute in the layout file.
+ *
+ * <p>SurfaceView is recommended in most cases for saving battery life. TextureView might be
+ * preferred for supporting various UIs such as animation and translucency.
  *
  * <h3 id="LegacyVideoView">Comparison with android.widget.VideoView</h3>
+ *
  * These are the main differences between the media2 VideoView widget and the older android widget:
+ *
  * <ul>
- * <li>
- *     {@link android.widget.VideoView android.widget.VideoView} creates a
- *     {@link android.media.MediaPlayer} instance internally and wraps playback APIs around it.
- *     <p>
- *     {@link VideoView androidx.media2.widget.VideoView} does not create a player instance
- *     internally. Instead, either a {@link SessionPlayer} or a {@link MediaController} instance
- *     should be created externally and link to {@link VideoView} using
- *     {@link #setPlayer(SessionPlayer)} or {@link #setMediaController(MediaController)},
- *     respectively.
- * <li>
- *     {@link android.widget.VideoView android.widget.VideoView} inherits from the SurfaceView
- *     class.
- *     <p>
- *     {@link VideoView androidx.media2.widget.VideoView} inherits from ViewGroup and can render
- *     videos using SurfaceView or TextureView, depending on your choice.
- * <li>
- *     A {@link VideoView} can respond to media key events if you call {@link #setMediaController}
- *     to link it to a {@link MediaController} that's connected to an active {@link MediaSession}.
+ *   <li>{@link android.widget.VideoView android.widget.VideoView} creates a {@link
+ *       android.media.MediaPlayer} instance internally and wraps playback APIs around it.
+ *       <p>{@link VideoView androidx.media2.widget.VideoView} does not create a player instance
+ *       internally. Instead, either a {@link androidx.media2.common.SessionPlayer} or a {@link
+ *       androidx.media2.session.MediaController} instance should be created externally and link to
+ *       {@link VideoView} using {@link #setPlayer(androidx.media2.common.SessionPlayer)} or {@link
+ *       #setMediaController(androidx.media2.session.MediaController)}, respectively.
+ *   <li>{@link android.widget.VideoView android.widget.VideoView} inherits from the SurfaceView
+ *       class.
+ *       <p>{@link VideoView androidx.media2.widget.VideoView} inherits from ViewGroup and can
+ *       render videos using SurfaceView or TextureView, depending on your choice.
+ *   <li>A {@link VideoView} can respond to media key events if you call {@link #setMediaController}
+ *       to link it to a {@link androidx.media2.session.MediaController} that's connected to an
+ *       active {@link androidx.media2.session.MediaSession}.
  * </ul>
  *
  * <h3 id="DisplayMetadata">Displaying Metadata</h3>
+ *
  * When you play music only (sound with no video), VideoView can display album art and other
- * metadata by calling {@link MediaItem#setMetadata(MediaMetadata)}.
- * The following table shows the metadata displayed by the VideoView, and the default values
- * assigned if the keys are not set:
+ * metadata by calling {@link
+ * androidx.media2.common.MediaItem#setMetadata(androidx.media2.common.MediaMetadata)}. The
+ * following table shows the metadata displayed by the VideoView, and the default values assigned if
+ * the keys are not set:
+ *
  * <table>
  *     <tr><th>Key</th><th>Default</th></tr>
- *     <tr><td>{@link MediaMetadata#METADATA_KEY_TITLE}</td>
+ *     <tr><td>{@link androidx.media2.common.MediaMetadata#METADATA_KEY_TITLE}</td>
  *     <td>{@link androidx.media2.widget.R.string#mcv2_music_title_unknown_text}</td></tr>
- *     <tr><td>{@link MediaMetadata#METADATA_KEY_ARTIST}</td>
+ *     <tr><td>{@link androidx.media2.common.MediaMetadata#METADATA_KEY_ARTIST}</td>
  *     <td>{@link androidx.media2.widget.R.string#mcv2_music_artist_unknown_text}</td></tr>
- *     <tr><td>{@link MediaMetadata#METADATA_KEY_ALBUM_ART}</td>
+ *     <tr><td>{@link androidx.media2.common.MediaMetadata#METADATA_KEY_ALBUM_ART}</td>
  *     <td>{@link androidx.media2.widget.R.drawable#media2_widget_ic_default_album_image}</td></tr>
  *     </table>
- * <p>
- * Note: VideoView does not retain its full state when going into the background. In particular, it
- * does not save, and does not restore the current play state, play position, selected tracks.
- * Applications should save and restore these on their own in
- * {@link android.app.Activity#onSaveInstanceState} and
- * {@link android.app.Activity#onRestoreInstanceState}.
- * <p> Attributes :
+ *
+ * <p>Note: VideoView does not retain its full state when going into the background. In particular,
+ * it does not save, and does not restore the current play state, play position, selected tracks.
+ * Applications should save and restore these on their own in {@link
+ * android.app.Activity#onSaveInstanceState} and {@link
+ * android.app.Activity#onRestoreInstanceState}.
+ *
+ * <p>Attributes :
+ *
  * <ul>
- *     <li> {@link androidx.media2.widget.R.attr#enableControlView}
- *     <li> {@link androidx.media2.widget.R.attr#viewType}
+ *   <li>{@link androidx.media2.widget.R.attr#enableControlView}
+ *   <li>{@link androidx.media2.widget.R.attr#viewType}
  * </ul>
- * <p> Example of attributes for a VideoView with TextureView and no attached control view:
- * <pre> {@code
- *  <androidx.media2.widget.VideoView
- *      android:id="@+id/video_view"
- *      widget:enableControlView="false"
- *      widget:viewType="textureView"
- *  />}</pre>
+ *
+ * <p>Example of attributes for a VideoView with TextureView and no attached control view:
+ *
+ * <pre>{@code
+ * <androidx.media2.widget.VideoView
+ *     android:id="@+id/video_view"
+ *     widget:enableControlView="false"
+ *     widget:viewType="textureView"
+ * />
+ * }</pre>
  *
  * @see MediaControlView
- * @see SessionPlayer
- * @see MediaController
+ * @see androidx.media2.common.SessionPlayer
+ * @see androidx.media2.session.MediaController
+ * @deprecated androidx.media2 is deprecated. Please migrate to <a
+ *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
  */
+@Deprecated
 public class VideoView extends SelectiveLayout {
     @IntDef({
             VIEW_TYPE_TEXTUREVIEW,
@@ -198,11 +209,11 @@
 
     int mVideoTrackCount;
     int mAudioTrackCount;
-    Map<TrackInfo, SubtitleTrack> mSubtitleTracks;
+    Map<androidx.media2.common.SessionPlayer.TrackInfo, SubtitleTrack> mSubtitleTracks;
     SubtitleController mSubtitleController;
 
     // selected subtitle track info as MediaPlayer returns
-    TrackInfo mSelectedSubtitleTrackInfo;
+    androidx.media2.common.SessionPlayer.TrackInfo mSelectedSubtitleTrackInfo;
 
     SubtitleAnchorView mSubtitleAnchorView;
 
@@ -289,30 +300,34 @@
         mSubtitleAnchorView.setBackgroundColor(0);
         addView(mSubtitleAnchorView, mSelectiveLayoutParams);
 
-        SubtitleController.Listener listener = new SubtitleController.Listener() {
-            @Override
-            public void onSubtitleTrackSelected(SubtitleTrack track) {
-                // Track deselected
-                if (track == null) {
-                    mSelectedSubtitleTrackInfo = null;
-                    mSubtitleAnchorView.setVisibility(View.GONE);
-                    return;
-                }
+        SubtitleController.Listener listener =
+                new SubtitleController.Listener() {
+                    @Override
+                    public void onSubtitleTrackSelected(SubtitleTrack track) {
+                        // Track deselected
+                        if (track == null) {
+                            mSelectedSubtitleTrackInfo = null;
+                            mSubtitleAnchorView.setVisibility(View.GONE);
+                            return;
+                        }
 
-                // Track selected
-                TrackInfo info = null;
-                for (Map.Entry<TrackInfo, SubtitleTrack> pair : mSubtitleTracks.entrySet()) {
-                    if (pair.getValue() == track) {
-                        info = pair.getKey();
-                        break;
+                        // Track selected
+                        androidx.media2.common.SessionPlayer.TrackInfo info = null;
+                        for (Map.Entry<
+                                        androidx.media2.common.SessionPlayer.TrackInfo,
+                                        SubtitleTrack>
+                                pair : mSubtitleTracks.entrySet()) {
+                            if (pair.getValue() == track) {
+                                info = pair.getKey();
+                                break;
+                            }
+                        }
+                        if (info != null) {
+                            mSelectedSubtitleTrackInfo = info;
+                            mSubtitleAnchorView.setVisibility(View.VISIBLE);
+                        }
                     }
-                }
-                if (info != null) {
-                    mSelectedSubtitleTrackInfo = info;
-                    mSubtitleAnchorView.setVisibility(View.VISIBLE);
-                }
-            }
-        };
+                };
         mSubtitleController = new SubtitleController(context, null, listener);
         mSubtitleController.registerRenderer(new Cea608CaptionRenderer(context));
         mSubtitleController.registerRenderer(new Cea708CaptionRenderer(context));
@@ -355,21 +370,26 @@
     }
 
     /**
-     * Sets {@link MediaController} to display media content.
-     * Setting a {@link MediaController} will unset any {@link MediaController} or
-     * {@link SessionPlayer} that was previously set.
-     * <p>
-     * If VideoView has a {@link MediaControlView} instance, this controller will also be set to it.
-     * <p>
-     * Calling this method will automatically set VideoView's surface to {@link MediaController}
-     * by calling {@link MediaController#setSurface(Surface)}. If the {@link MediaController} is
-     * connected to a {@link MediaSession} and that {@link MediaSession} is associated with a
-     * {@link SessionPlayer}, VideoView's surface will be set to that {@link SessionPlayer}.
+     * Sets {@link androidx.media2.session.MediaController} to display media content. Setting a
+     * {@link androidx.media2.session.MediaController} will unset any {@link
+     * androidx.media2.session.MediaController} or {@link androidx.media2.common.SessionPlayer} that
+     * was previously set.
+     *
+     * <p>If VideoView has a {@link MediaControlView} instance, this controller will also be set to
+     * it.
+     *
+     * <p>Calling this method will automatically set VideoView's surface to {@link
+     * androidx.media2.session.MediaController} by calling {@link
+     * androidx.media2.session.MediaController#setSurface(Surface)}. If the {@link
+     * androidx.media2.session.MediaController} is connected to a {@link
+     * androidx.media2.session.MediaSession} and that {@link androidx.media2.session.MediaSession}
+     * is associated with a {@link androidx.media2.common.SessionPlayer}, VideoView's surface will
+     * be set to that {@link androidx.media2.common.SessionPlayer}.
      *
      * @param controller the controller
      * @see #setPlayer
      */
-    public void setMediaController(@NonNull MediaController controller) {
+    public void setMediaController(@NonNull androidx.media2.session.MediaController controller) {
         if (controller == null) {
             throw new NullPointerException("controller must not be null");
         }
@@ -392,21 +412,21 @@
         }
     }
 
-
     /**
-     * Sets {@link SessionPlayer} to display media content.
-     * Setting a SessionPlayer will unset any MediaController or SessionPlayer that was previously
-     * set.
-     * <p>
-     * If VideoView has a {@link MediaControlView} instance, this player will also be set to it.
-     * <p>
-     * Calling this method will automatically set VideoView's surface to {@link SessionPlayer}
-     * by calling {@link SessionPlayer#setSurface(Surface)}.
+     * Sets {@link androidx.media2.common.SessionPlayer} to display media content. Setting a
+     * androidx.media2.common.SessionPlayer will unset any androidx.media2.session.MediaController
+     * or androidx.media2.common.SessionPlayer that was previously set.
+     *
+     * <p>If VideoView has a {@link MediaControlView} instance, this player will also be set to it.
+     *
+     * <p>Calling this method will automatically set VideoView's surface to {@link
+     * androidx.media2.common.SessionPlayer} by calling {@link
+     * androidx.media2.common.SessionPlayer#setSurface(Surface)}.
      *
      * @param player the player
      * @see #setMediaController
      */
-    public void setPlayer(@NonNull SessionPlayer player) {
+    public void setPlayer(@NonNull androidx.media2.common.SessionPlayer player) {
         if (player == null) {
             throw new NullPointerException("player must not be null");
         }
@@ -430,16 +450,17 @@
     }
 
     /**
-     * Sets {@link MediaControlView} instance. It will replace the previously assigned
-     * {@link MediaControlView} instance if any.
-     * <p>
-     * If a {@link MediaController} or a {@link SessionPlayer} instance has been set to
-     * {@link VideoView}, the same instance will be set to {@link MediaControlView}.
+     * Sets {@link MediaControlView} instance. It will replace the previously assigned {@link
+     * MediaControlView} instance if any.
+     *
+     * <p>If a {@link androidx.media2.session.MediaController} or a {@link
+     * androidx.media2.common.SessionPlayer} instance has been set to {@link VideoView}, the same
+     * instance will be set to {@link MediaControlView}.
      *
      * @param mediaControlView a {@link MediaControlView} instance.
      * @param intervalMs time interval in milliseconds until {@link MediaControlView} transitions
-     *                   into a different mode. -1 can be set to disable all UI transitions. See
-     *                   {@link MediaControlView} Javadoc Section "UI transitions" for details.
+     *     into a different mode. -1 can be set to disable all UI transitions. See {@link
+     *     MediaControlView} Javadoc Section "UI transitions" for details.
      */
     public void setMediaControlView(@NonNull MediaControlView mediaControlView, long intervalMs) {
         if (mMediaControlView != null) {
@@ -578,15 +599,17 @@
     ///////////////////////////////////////////////////
     boolean isMediaPrepared() {
         return mPlayer != null
-                && mPlayer.getPlayerState() != SessionPlayer.PLAYER_STATE_ERROR
-                && mPlayer.getPlayerState() != SessionPlayer.PLAYER_STATE_IDLE;
+                && mPlayer.getPlayerState()
+                        != androidx.media2.common.SessionPlayer.PLAYER_STATE_ERROR
+                && mPlayer.getPlayerState()
+                        != androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
     }
 
     boolean hasActualVideo() {
         if (mVideoTrackCount > 0) {
             return true;
         }
-        VideoSize videoSize = mPlayer.getVideoSize();
+        androidx.media2.common.VideoSize videoSize = mPlayer.getVideoSize();
         if (videoSize.getHeight() > 0 && videoSize.getWidth() > 0) {
             Log.w(TAG, "video track count is zero, but it renders video. size: "
                     + videoSize.getWidth() + "/" + videoSize.getHeight());
@@ -599,42 +622,54 @@
         return !hasActualVideo() && mAudioTrackCount > 0;
     }
 
-    void updateTracks(PlayerWrapper player, List<TrackInfo> trackInfos) {
+    void updateTracks(
+            PlayerWrapper player, List<androidx.media2.common.SessionPlayer.TrackInfo> trackInfos) {
         mSubtitleTracks = new LinkedHashMap<>();
         mVideoTrackCount = 0;
         mAudioTrackCount = 0;
         for (int i = 0; i < trackInfos.size(); i++) {
-            TrackInfo trackInfo = trackInfos.get(i);
+            androidx.media2.common.SessionPlayer.TrackInfo trackInfo = trackInfos.get(i);
             int trackType = trackInfos.get(i).getTrackType();
-            if (trackType == TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
+            if (trackType
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) {
                 mVideoTrackCount++;
-            } else if (trackType == TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
+            } else if (trackType
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) {
                 mAudioTrackCount++;
-            } else if (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+            } else if (trackType
+                    == androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
                 SubtitleTrack track = mSubtitleController.addTrack(trackInfo.getFormat());
                 if (track != null) {
                     mSubtitleTracks.put(trackInfo, track);
                 }
             }
         }
-        mSelectedSubtitleTrackInfo = player.getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE);
+        mSelectedSubtitleTrackInfo =
+                player.getSelectedTrack(
+                        androidx.media2.common.SessionPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE);
     }
 
-    void updateMusicView(MediaItem item) {
+    void updateMusicView(androidx.media2.common.MediaItem item) {
         boolean shouldShowMusicView = item != null && isCurrentItemMusic();
         if (shouldShowMusicView) {
             mMusicView.setVisibility(View.VISIBLE);
 
-            MediaMetadata metadata = item.getMetadata();
+            androidx.media2.common.MediaMetadata metadata = item.getMetadata();
             Resources resources = getResources();
 
             Drawable albumDrawable = getAlbumArt(metadata,
                     ContextCompat.getDrawable(
                             getContext(), R.drawable.media2_widget_ic_default_album_image));
-            String title = getString(metadata, MediaMetadata.METADATA_KEY_TITLE,
-                    resources.getString(R.string.mcv2_music_title_unknown_text));
-            String artist = getString(metadata, MediaMetadata.METADATA_KEY_ARTIST,
-                    resources.getString(R.string.mcv2_music_artist_unknown_text));
+            String title =
+                    getString(
+                            metadata,
+                            androidx.media2.common.MediaMetadata.METADATA_KEY_TITLE,
+                            resources.getString(R.string.mcv2_music_title_unknown_text));
+            String artist =
+                    getString(
+                            metadata,
+                            androidx.media2.common.MediaMetadata.METADATA_KEY_ARTIST,
+                            resources.getString(R.string.mcv2_music_artist_unknown_text));
 
             mMusicView.setAlbumDrawable(albumDrawable);
             mMusicView.setTitleText(title);
@@ -652,7 +687,7 @@
         try {
             int resultCode = mPlayer.setSurface(null).get(100, TimeUnit.MILLISECONDS)
                     .getResultCode();
-            if (resultCode != BaseResult.RESULT_SUCCESS) {
+            if (resultCode != androidx.media2.common.BaseResult.RESULT_SUCCESS) {
                 Log.e(TAG, "calling setSurface(null) was not "
                         + "successful. ResultCode: " + resultCode);
             }
@@ -663,30 +698,39 @@
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     void resetPlayerSurfaceWithNullAsync() {
-        ListenableFuture<? extends BaseResult> future = mPlayer.setSurface(null);
+        ListenableFuture<? extends androidx.media2.common.BaseResult> future =
+                mPlayer.setSurface(null);
         future.addListener(
                 new Runnable() {
                     @Override
                     public void run() {
                         try {
                             int resultCode = future.get().getResultCode();
-                            if (resultCode != BaseResult.RESULT_SUCCESS) {
-                                Log.e(TAG, "calling setSurface(null) was not "
-                                        + "successful. ResultCode: " + resultCode);
+                            if (resultCode != androidx.media2.common.BaseResult.RESULT_SUCCESS) {
+                                Log.e(
+                                        TAG,
+                                        "calling setSurface(null) was not "
+                                                + "successful. ResultCode: "
+                                                + resultCode);
                             }
                         } catch (ExecutionException | InterruptedException e) {
                             Log.e(TAG, "calling setSurface(null) was not successful.", e);
                         }
                     }
-                }, ContextCompat.getMainExecutor(getContext()));
+                },
+                ContextCompat.getMainExecutor(getContext()));
     }
 
-    private Drawable getAlbumArt(@NonNull MediaMetadata metadata, Drawable defaultDrawable) {
+    private Drawable getAlbumArt(
+            @NonNull androidx.media2.common.MediaMetadata metadata, Drawable defaultDrawable) {
         Drawable drawable = defaultDrawable;
         Bitmap bitmap = null;
 
-        if (metadata != null && metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ART)) {
-            bitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+        if (metadata != null
+                && metadata.containsKey(
+                        androidx.media2.common.MediaMetadata.METADATA_KEY_ALBUM_ART)) {
+            bitmap =
+                    metadata.getBitmap(androidx.media2.common.MediaMetadata.METADATA_KEY_ALBUM_ART);
         }
         if (bitmap != null) {
             Palette.Builder builder = Palette.from(bitmap);
@@ -705,7 +749,9 @@
         return drawable;
     }
 
-    private String getString(@NonNull MediaMetadata metadata, String stringKey,
+    private String getString(
+            @NonNull androidx.media2.common.MediaMetadata metadata,
+            String stringKey,
             String defaultValue) {
         String value = (metadata == null) ? defaultValue : metadata.getString(stringKey);
         return value == null ? defaultValue : value;
@@ -724,14 +770,17 @@
         }
 
         @Override
-        void onVideoSizeChanged(@NonNull PlayerWrapper player, @NonNull VideoSize videoSize) {
+        void onVideoSizeChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.VideoSize videoSize) {
             if (DEBUG) {
-                Log.d(TAG, "onVideoSizeChanged(): size: " + videoSize);
+                Log.d(TAG, "onandroidx.media2.common.VideoSizeChanged(): size: " + videoSize);
             }
             if (shouldIgnoreCallback(player)) return;
             if (mVideoTrackCount == 0 && videoSize.getHeight() > 0 && videoSize.getWidth() > 0) {
                 if (isMediaPrepared()) {
-                    List<TrackInfo> trackInfos = player.getTracks();
+                    List<androidx.media2.common.SessionPlayer.TrackInfo> trackInfos =
+                            player.getTracks();
                     if (trackInfos != null) {
                         updateTracks(player, trackInfos);
                     }
@@ -743,16 +792,25 @@
         }
 
         @Override
-        void onSubtitleData(@NonNull PlayerWrapper player, @NonNull MediaItem item,
-                @NonNull TrackInfo track, @NonNull SubtitleData data) {
+        void onSubtitleData(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.MediaItem item,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo track,
+                @NonNull androidx.media2.common.SubtitleData data) {
             if (DEBUG) {
-                Log.d(TAG, "onSubtitleData():"
-                        + " TrackInfo: " + track
-                        + ", getCurrentPosition: " + player.getCurrentPosition()
-                        + ", getStartTimeUs(): " + data.getStartTimeUs()
-                        + ", diff: "
-                        + (data.getStartTimeUs() / 1000 - player.getCurrentPosition())
-                        + "ms, getDurationUs(): " + data.getDurationUs());
+                Log.d(
+                        TAG,
+                        "onandroidx.media2.common.SubtitleData():"
+                                + " androidx.media2.common.SessionPlayer.TrackInfo: "
+                                + track
+                                + ", getCurrentPosition: "
+                                + player.getCurrentPosition()
+                                + ", getStartTimeUs(): "
+                                + data.getStartTimeUs()
+                                + ", diff: "
+                                + (data.getStartTimeUs() / 1000 - player.getCurrentPosition())
+                                + "ms, getDurationUs(): "
+                                + data.getDurationUs());
             }
             if (shouldIgnoreCallback(player)) return;
             if (!track.equals(mSelectedSubtitleTrackInfo)) {
@@ -770,15 +828,20 @@
                 Log.d(TAG, "onPlayerStateChanged(): state: " + state);
             }
             if (shouldIgnoreCallback(player)) return;
-            if (state == SessionPlayer.PLAYER_STATE_ERROR) {
+            if (state == androidx.media2.common.SessionPlayer.PLAYER_STATE_ERROR) {
                 // TODO: Show error state (b/123498635)
             }
         }
 
         @Override
-        void onCurrentMediaItemChanged(@NonNull PlayerWrapper player, @Nullable MediaItem item) {
+        void onCurrentMediaItemChanged(
+                @NonNull PlayerWrapper player, @Nullable androidx.media2.common.MediaItem item) {
             if (DEBUG) {
-                Log.d(TAG, "onCurrentMediaItemChanged(): MediaItem: " + item);
+                Log.d(
+                        TAG,
+                        "onCurrentMediaItemChanged():"
+                                + " androidx.media2.common.MediaItem: "
+                                + item);
             }
             if (shouldIgnoreCallback(player)) return;
 
@@ -786,9 +849,14 @@
         }
 
         @Override
-        void onTracksChanged(@NonNull PlayerWrapper player, @NonNull List<TrackInfo> tracks) {
+        void onTracksChanged(
+                @NonNull PlayerWrapper player,
+                @NonNull List<androidx.media2.common.SessionPlayer.TrackInfo> tracks) {
             if (DEBUG) {
-                Log.d(TAG, "onTrackInfoChanged(): tracks: " + tracks);
+                Log.d(
+                        TAG,
+                        "onandroidx.media2.common.SessionPlayer.TrackInfoChanged(): tracks: "
+                                + tracks);
             }
             if (shouldIgnoreCallback(player)) return;
             updateTracks(player, tracks);
@@ -796,7 +864,9 @@
         }
 
         @Override
-        void onTrackSelected(@NonNull PlayerWrapper player, @NonNull TrackInfo trackInfo) {
+        void onTrackSelected(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             if (DEBUG) {
                 Log.d(TAG, "onTrackSelected(): selected track: " + trackInfo);
             }
@@ -808,7 +878,9 @@
         }
 
         @Override
-        void onTrackDeselected(@NonNull PlayerWrapper player, @NonNull TrackInfo trackInfo) {
+        void onTrackDeselected(
+                @NonNull PlayerWrapper player,
+                @NonNull androidx.media2.common.SessionPlayer.TrackInfo trackInfo) {
             if (DEBUG) {
                 Log.d(TAG, "onTrackDeselected(): deselected track: " + trackInfo);
             }
@@ -838,7 +910,11 @@
 
     /**
      * Interface definition of a callback to be invoked when the view type has been changed.
+     *
+     * @deprecated androidx.media2 is deprecated. Please migrate to <a
+     *     href="https://developer.android.com/guide/topics/media/media3">androidx.media3</a>.
      */
+    @Deprecated
     public interface OnViewTypeChangedListener {
         /**
          * Called when the view type has been changed.
diff --git a/mediarouter/mediarouter/api/current.txt b/mediarouter/mediarouter/api/current.txt
index 5d4d482..7d7510b 100644
--- a/mediarouter/mediarouter/api/current.txt
+++ b/mediarouter/mediarouter/api/current.txt
@@ -190,6 +190,7 @@
     method @Deprecated public boolean isConnecting();
     method public boolean isDynamicGroupRoute();
     method public boolean isEnabled();
+    method public boolean isSystemRoute();
     method public boolean isValid();
     method public boolean isVisibilityPublic();
   }
@@ -443,6 +444,7 @@
     method public boolean isDeviceSpeaker();
     method public boolean isEnabled();
     method @MainThread public boolean isSelected();
+    method public boolean isSystemRoute();
     method @MainThread public boolean matchesSelector(androidx.mediarouter.media.MediaRouteSelector);
     method @MainThread public void requestSetVolume(int);
     method @MainThread public void requestUpdateVolume(int);
diff --git a/mediarouter/mediarouter/api/restricted_current.txt b/mediarouter/mediarouter/api/restricted_current.txt
index 5d4d482..7d7510b 100644
--- a/mediarouter/mediarouter/api/restricted_current.txt
+++ b/mediarouter/mediarouter/api/restricted_current.txt
@@ -190,6 +190,7 @@
     method @Deprecated public boolean isConnecting();
     method public boolean isDynamicGroupRoute();
     method public boolean isEnabled();
+    method public boolean isSystemRoute();
     method public boolean isValid();
     method public boolean isVisibilityPublic();
   }
@@ -443,6 +444,7 @@
     method public boolean isDeviceSpeaker();
     method public boolean isEnabled();
     method @MainThread public boolean isSelected();
+    method public boolean isSystemRoute();
     method @MainThread public boolean matchesSelector(androidx.mediarouter.media.MediaRouteSelector);
     method @MainThread public void requestSetVolume(int);
     method @MainThread public void requestUpdateVolume(int);
diff --git a/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouteDescriptorTest.java b/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouteDescriptorTest.java
index 0d3b08c..02eec67 100644
--- a/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouteDescriptorTest.java
+++ b/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouteDescriptorTest.java
@@ -111,6 +111,27 @@
 
     @Test
     @SmallTest
+    public void testDefaultIsSystemRouteReturnsFalse() {
+        MediaRouteDescriptor routeDescriptor =
+                new MediaRouteDescriptor.Builder(FAKE_MEDIA_ROUTE_ID_1, FAKE_MEDIA_ROUTE_NAME)
+                        .build();
+
+        assertFalse(routeDescriptor.isSystemRoute());
+    }
+
+    @Test
+    @SmallTest
+    public void testSetIsSystemRoute() {
+        MediaRouteDescriptor routeDescriptor =
+                new MediaRouteDescriptor.Builder(FAKE_MEDIA_ROUTE_ID_1, FAKE_MEDIA_ROUTE_NAME)
+                        .setIsSystemRoute(true)
+                        .build();
+
+        assertTrue(routeDescriptor.isSystemRoute());
+    }
+
+    @Test
+    @SmallTest
     public void testDefaultVisibilityIsPublic() {
         MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
                 FAKE_MEDIA_ROUTE_ID_1, FAKE_MEDIA_ROUTE_NAME)
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
index 76ceab1..e407e5a 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
@@ -722,7 +722,9 @@
                 if (sourceIndex < 0) {
                     // 1. Add the route to the list.
                     String uniqueId = assignRouteUniqueId(provider, id);
-                    MediaRouter.RouteInfo route = new MediaRouter.RouteInfo(provider, id, uniqueId);
+                    MediaRouter.RouteInfo route =
+                            new MediaRouter.RouteInfo(
+                                    provider, id, uniqueId, routeDescriptor.isSystemRoute());
 
                     provider.mRoutes.add(targetIndex++, route);
                     mRoutes.add(route);
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteDescriptor.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteDescriptor.java
index e053d4f..19588d1 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteDescriptor.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteDescriptor.java
@@ -53,6 +53,7 @@
     static final String KEY_DESCRIPTION = "status";
     static final String KEY_ICON_URI = "iconUri";
     static final String KEY_ENABLED = "enabled";
+    static final String KEY_IS_SYSTEM_ROUTE = "isSystemRoute";
     static final String IS_DYNAMIC_GROUP_ROUTE = "isDynamicGroupRoute";
     static final String KEY_CONNECTING = "connecting";
     static final String KEY_CONNECTION_STATE = "connectionState";
@@ -152,6 +153,20 @@
     }
 
     /**
+     * Returns {@code true} if this route is a system route.
+     *
+     * <p>System routes are routes controlled by the system, like the device's built-in speakers,
+     * wired headsets, and bluetooth devices.
+     *
+     * <p>To use system routes, your application should write media sample data to a media framework
+     * API, typically via <a
+     * href="https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer">Exoplayer</a>.
+     */
+    public boolean isSystemRoute() {
+        return mBundle.getBoolean(KEY_IS_SYSTEM_ROUTE, false);
+    }
+
+    /**
      * Returns if this route is a dynamic group route.
      * <p>
      * {@link MediaRouteProvider} creates a dynamic group route when
@@ -378,6 +393,7 @@
                 + ", description=" + getDescription()
                 + ", iconUri=" + getIconUri()
                 + ", isEnabled=" + isEnabled()
+                + ", isSystemRoute=" + isSystemRoute()
                 + ", connectionState=" + getConnectionState()
                 + ", controlFilters=" + Arrays.toString(getControlFilters().toArray())
                 + ", playbackType=" + getPlaybackType()
@@ -607,6 +623,18 @@
         }
 
         /**
+         * Sets whether the route is a system route.
+         *
+         * @see MediaRouteDescriptor#isSystemRoute()
+         */
+        @RestrictTo(LIBRARY)
+        @NonNull
+        public Builder setIsSystemRoute(boolean isSystemRoute) {
+            mBundle.putBoolean(KEY_IS_SYSTEM_ROUTE, isSystemRoute);
+            return this;
+        }
+
+        /**
          * Sets whether the route is a dynamic group route.
          * @see #isDynamicGroupRoute()
          */
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 f66d6748..7bfccd0 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -1079,6 +1079,7 @@
         private String mDescription;
         private Uri mIconUri;
         boolean mEnabled;
+        private final boolean mIsSystemRoute;
         private @ConnectionState int mConnectionState;
         private boolean mCanDisconnect;
         private final ArrayList<IntentFilter> mControlFilters = new ArrayList<>();
@@ -1300,10 +1301,19 @@
         // Should match to SystemMediaRouteProvider.PACKAGE_NAME.
         static final String SYSTEM_MEDIA_ROUTE_PROVIDER_PACKAGE_NAME = "android";
 
-        RouteInfo(ProviderInfo provider, String descriptorId, String uniqueId) {
+        /* package */ RouteInfo(ProviderInfo provider, String descriptorId, String uniqueId) {
+            this(provider, descriptorId, uniqueId, /* isSystemRoute */ false);
+        }
+
+        /* package */ RouteInfo(
+                ProviderInfo provider,
+                String descriptorId,
+                String uniqueId,
+                boolean isSystemRoute) {
             mProvider = provider;
             mDescriptorId = descriptorId;
             mUniqueId = uniqueId;
+            mIsSystemRoute = isSystemRoute;
         }
 
         /**
@@ -1381,6 +1391,20 @@
         }
 
         /**
+         * Returns {@code true} if this route is a system route.
+         *
+         * <p>System routes are routes controlled by the system, like the device's built-in
+         * speakers, wired headsets, and bluetooth devices.
+         *
+         * <p>To use system routes, your application should write media sample data to a media
+         * framework API, typically via <a
+         * href="https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer">Exoplayer</a>.
+         */
+        public boolean isSystemRoute() {
+            return mIsSystemRoute;
+        }
+
+        /**
          * Returns true if the route is in the process of connecting and is not
          * yet ready for use.
          *
@@ -1901,6 +1925,7 @@
                     .append(", description=").append(mDescription)
                     .append(", iconUri=").append(mIconUri)
                     .append(", enabled=").append(mEnabled)
+                    .append(", isSystemRoute=").append(mIsSystemRoute)
                     .append(", connectionState=").append(mConnectionState)
                     .append(", canDisconnect=").append(mCanDisconnect)
                     .append(", playbackType=").append(mPlaybackType)
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/SystemMediaRouteProvider.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/SystemMediaRouteProvider.java
index ab200f6..3a64a5e 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/SystemMediaRouteProvider.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/SystemMediaRouteProvider.java
@@ -140,15 +140,17 @@
             Resources r = getContext().getResources();
             int maxVolume = mAudioManager.getStreamMaxVolume(PLAYBACK_STREAM);
             mLastReportedVolume = mAudioManager.getStreamVolume(PLAYBACK_STREAM);
-            MediaRouteDescriptor defaultRoute = new MediaRouteDescriptor.Builder(
-                    DEFAULT_ROUTE_ID, r.getString(R.string.mr_system_route_name))
-                    .addControlFilters(CONTROL_FILTERS)
-                    .setPlaybackStream(PLAYBACK_STREAM)
-                    .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL)
-                    .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
-                    .setVolumeMax(maxVolume)
-                    .setVolume(mLastReportedVolume)
-                    .build();
+            MediaRouteDescriptor defaultRoute =
+                    new MediaRouteDescriptor.Builder(
+                                    DEFAULT_ROUTE_ID, r.getString(R.string.mr_system_route_name))
+                            .addControlFilters(CONTROL_FILTERS)
+                            .setPlaybackStream(PLAYBACK_STREAM)
+                            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL)
+                            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
+                            .setVolumeMax(maxVolume)
+                            .setVolume(mLastReportedVolume)
+                            .setIsSystemRoute(true)
+                            .build();
 
             MediaRouteProviderDescriptor providerDescriptor =
                     new MediaRouteProviderDescriptor.Builder()
@@ -616,6 +618,7 @@
             builder.setVolumeMax(MediaRouterApi16Impl.RouteInfo.getVolumeMax(record.mRoute));
             builder.setVolumeHandling(
                     MediaRouterApi16Impl.RouteInfo.getVolumeHandling(record.mRoute));
+            builder.setIsSystemRoute(true);
         }
 
         protected void updateUserRouteProperties(UserRouteRecord record) {
diff --git a/recyclerview/recyclerview/lint-baseline.xml b/recyclerview/recyclerview/lint-baseline.xml
index 1e9ffd1..f004d3d 100644
--- a/recyclerview/recyclerview/lint-baseline.xml
+++ b/recyclerview/recyclerview/lint-baseline.xml
@@ -263,60 +263,6 @@
     </issue>
 
     <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/recyclerview/widget/GridLayoutManager.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is never &lt; 19"
-        errorLine1="    static final boolean FORCE_INVALIDATE_DISPLAY_LIST = Build.VERSION.SDK_INT == 18"
-        errorLine2="                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/recyclerview/widget/RecyclerView.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="    static final boolean POST_UPDATES_ON_ANIMATION = Build.VERSION.SDK_INT >= 16;"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/recyclerview/widget/RecyclerView.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is never &lt; 19"
-        errorLine1="    private static final boolean FORCE_ABS_FOCUS_SEARCH_DIRECTION = Build.VERSION.SDK_INT &lt;= 15;"
-        errorLine2="                                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/recyclerview/widget/RecyclerView.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is never &lt; 19"
-        errorLine1="    private static final boolean IGNORE_DETACHED_FOCUSED_CHILD = Build.VERSION.SDK_INT &lt;= 15;"
-        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/recyclerview/widget/RecyclerView.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is never &lt; 19"
-        errorLine1="        if (Build.VERSION.SDK_INT &lt; 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/recyclerview/widget/RecyclerView.java"/>
-    </issue>
-
-    <issue
         id="KotlinPropertyAccess"
         message="This method should be called `getHasFixedSize` such that `hasFixedSize` can be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
         errorLine1="    public boolean hasFixedSize() {"
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
index 2f1a212..3b32bc6 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ConcatAdapterTest.kt
@@ -169,7 +169,6 @@
 
     @UiThreadTest
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     fun failedToRecycleTest() {
         val adapter1 = NestedTestAdapter(10)
         val adapter2 = NestedTestAdapter(5)
@@ -393,7 +392,6 @@
 
     @UiThreadTest
     @Test
-    @SdkSuppress(minSdkVersion = 16)
     public fun recycledViewPositions_failedRecycle() {
         val adapter1 = NestedTestAdapter(
             count = 5,
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerTest.java
index 1200b29..238289b 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerTest.java
@@ -811,13 +811,11 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     public void horizontalAccessibilitySpanIndices() throws Throwable {
         accessibilitySpanIndicesTest(HORIZONTAL);
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     public void verticalAccessibilitySpanIndices() throws Throwable {
         accessibilitySpanIndicesTest(VERTICAL);
     }
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerUiAutomationTests.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerUiAutomationTests.java
index 9349121..09ce118 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerUiAutomationTests.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/GridLayoutManagerUiAutomationTests.java
@@ -45,7 +45,6 @@
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = 18)
 public class GridLayoutManagerUiAutomationTests extends BaseGridLayoutManagerTest {
 
     private static final int DEFAULT_ACCESSIBILITY_EVENT_TIMEOUT_MILLIS = 5000;
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java
index 1017a03..37d32f9 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java
@@ -28,7 +28,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.animation.ValueAnimator;
-import android.os.Build;
 import android.view.Gravity;
 import android.view.ViewConfiguration;
 
@@ -37,7 +36,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.Suppress;
 import androidx.testutils.AnimationDurationScaleRule;
 import androidx.testutils.PollingCheck;
@@ -139,14 +137,12 @@
 
     // Test is disabled as it is flaky.
     @Suppress
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1)
     @Test
     public void swipeStartInRTL() throws Throwable {
         mSetupRTL = true;
         basicSwipeTest(START, START | END, getActivity().getWindow().getDecorView().getWidth());
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1)
     @Test
     @FlakyTest(bugId = 190192628)
     public void swipeEndInRTL() throws Throwable {
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerTest.java
index ba9d036..8541a57 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/LinearLayoutManagerTest.java
@@ -565,12 +565,6 @@
         }
     }
 
-    // Run this test on Jelly Bean and newer because clearFocus on API 15 will call
-    // requestFocus in ViewRootImpl when clearChildFocus is called. Whereas, in API 16 and above,
-    // this call is delayed until after onFocusChange callback is called. Thus on API 16+, there's a
-    // transient state of no child having focus during which onFocusChange is executed. This
-    // transient state does not exist on API 15-.
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     public void unfocusableScrollingWhenFocusCleared() throws Throwable {
         // The maximum number of child views that can be visible at any time.
@@ -828,7 +822,6 @@
         });
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     @Test
     public void hiddenNoneRemoveViewAccessibility() throws Throwable {
         // TODO(b/263592347): remove the RecyclerView.setDebugAssertionsEnabled calls
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt
index cc6560b..141a1025 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt
@@ -25,7 +25,6 @@
 import androidx.customview.poolingcontainer.addPoolingContainerListener
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.test.filters.SdkSuppress
 import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
 import androidx.testutils.AnimationDurationScaleRule
 import com.google.common.truth.Truth.assertThat
@@ -42,7 +41,6 @@
 
 @LargeTest
 @RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
 /**
  * Note: this test's structure largely parallels AndroidComposeViewsRecyclerViewTest
  * (though there are notable implementation differences)
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAccessibilityLifecycleTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAccessibilityLifecycleTest.java
index 4b71b5b..2e6e604 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAccessibilityLifecycleTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAccessibilityLifecycleTest.java
@@ -376,7 +376,6 @@
                 });
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void onInitNodeInfoWithNestedDelegateReturnsNodeProvider() throws Throwable {
         final AccessibilityNodeProviderCompat expectedNodeProvider =
@@ -432,7 +431,6 @@
                 });
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void performActionWithhNestedDelegate() throws Throwable {
         final int expectedActionId = 42;
@@ -450,7 +448,6 @@
                 });
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void performActionWithhNestedDelegateCallsView() throws Throwable {
         final int expectedActionId = 42;
@@ -478,7 +475,6 @@
                 });
     }
 
-    @SdkSuppress(minSdkVersion = 16)
     @Test
     public void customItemDelegate() throws Throwable {
         final RecyclerView recyclerView = new RecyclerView(getActivity()) {
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAnimationsTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAnimationsTest.java
index 5da188d..3ab549f 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAnimationsTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewAnimationsTest.java
@@ -26,7 +26,6 @@
 import static org.junit.Assert.fail;
 
 import android.graphics.Rect;
-import android.os.Build;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,7 +34,6 @@
 import androidx.core.view.ViewCompat;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.testutils.AnimationDurationScaleRule;
 import androidx.testutils.PollingCheck;
 
@@ -441,8 +439,6 @@
         });
     }
 
-    // Disable this test on ICS because it causes testing devices to freeze.
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     public void dontReuseHiddenViewOnInvalidate() throws Throwable {
         reuseHiddenViewTest(new ReuseTestCallback() {
@@ -733,13 +729,11 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN) // needed for hasTransientState
     public void removeSlideInViewLeftToSlideOutViewAndCancelAnimationInOnDetach() throws Throwable {
         removeSlideInViewLeftToSlideOutView(/* cancelViewPropertyAnimatorsInOnDetach= */ true);
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN) // needed for hasTransientState
     public void removeSlideInViewLeftToSlideOutView() throws Throwable {
         removeSlideInViewLeftToSlideOutView(/* cancelViewPropertyAnimatorsInOnDetach= */ false);
     }
@@ -868,7 +862,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     public void importantForAccessibilityWhileDetelingAuto() throws Throwable {
         runTestImportantForAccessibilityWhileDeteling(
                 ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO,
@@ -876,7 +869,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     public void importantForAccessibilityWhileDetelingNo() throws Throwable {
         runTestImportantForAccessibilityWhileDeteling(
                 ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO,
@@ -884,7 +876,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     public void importantForAccessibilityWhileDetelingNoHideDescandants() throws Throwable {
         runTestImportantForAccessibilityWhileDeteling(
                 ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
@@ -892,7 +883,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
     public void importantForAccessibilityWhileDetelingYes() throws Throwable {
         runTestImportantForAccessibilityWhileDeteling(
                 ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES,
@@ -1586,8 +1576,6 @@
         mLayoutManager.waitForLayout(2);
     }
 
-    // Run this test on Jelly Bean and newer because hasTransientState was introduced in API 16.
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     public void appCancelAnimationInDetach() throws Throwable {
         final View[] addedView = new View[2];
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewBasicTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewBasicTest.java
index 3a6ad4f..de765ab3 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewBasicTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewBasicTest.java
@@ -47,7 +47,6 @@
 import androidx.recyclerview.test.R;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
@@ -102,7 +101,6 @@
                 0, layoutManager.mLayoutCount);
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     @Ignore("b/236978861")
     public void setScrollContainer() {
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewFocusTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewFocusTest.java
index 7e1712d..868aa11 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewFocusTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewFocusTest.java
@@ -29,7 +29,6 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.rule.ActivityTestRule;
 
 import org.junit.Rule;
@@ -115,7 +114,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 17)
     public void focusSearch_horizontalRtlAndHasChildInDirection_findsCorrectChild()
             throws Throwable {
         setupRecyclerView(true, RecyclerView.HORIZONTAL, false);
@@ -154,7 +152,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 17)
     public void focusSearch_horizontalRtlAndHasChildInDirection_doesNotCallOnFocusSearchFailed()
             throws Throwable {
         setupRecyclerView(true, RecyclerView.HORIZONTAL, false);
@@ -189,7 +186,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 17)
     public void focusSearch_horizontalRtlAndDoesNotHaveChildInDirection_callsOnFocusSearchFailed()
             throws Throwable {
         setupRecyclerView(true, RecyclerView.HORIZONTAL, false);
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewLayoutTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewLayoutTest.java
index 0317e9d..c19f539 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewLayoutTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewLayoutTest.java
@@ -73,7 +73,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.Suppress;
 import androidx.testutils.AnimationDurationScaleRule;
 
@@ -2174,19 +2173,16 @@
         });
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     public void transientStateRecycleViaAdapter() throws Throwable {
         transientStateRecycleTest(true, false);
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     public void transientStateRecycleViaTransientStateCleanup() throws Throwable {
         transientStateRecycleTest(false, true);
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
     @Test
     public void transientStateDontRecycle() throws Throwable {
         transientStateRecycleTest(false, false);
@@ -2347,7 +2343,6 @@
         });
     }
 
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN) // transientState is API 16
     @Test
     public void avoidLeakingRecyclerViewIfViewIsNotRecycled() throws Throwable {
         final AtomicBoolean failedToRecycle = new AtomicBoolean(false);
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingA11yScrollTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingA11yScrollTest.java
index 0cf7769..25ece5f 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingA11yScrollTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrollingA11yScrollTest.java
@@ -40,7 +40,6 @@
 import androidx.core.view.ViewCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
 import androidx.testutils.ActivityScenarioResetRule;
 import androidx.testutils.ResettableActivityScenarioRule;
 
@@ -63,7 +62,6 @@
  */
 @RunWith(Parameterized.class)
 @LargeTest
-@SdkSuppress(minSdkVersion = 16)
 public class RecyclerViewNestedScrollingA11yScrollTest {
 
 
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewWithTransitionsTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewWithTransitionsTest.kt
index bdc75b9..9c59766 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewWithTransitionsTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewWithTransitionsTest.kt
@@ -16,20 +16,15 @@
 
 package androidx.recyclerview.widget
 
-import android.animation.LayoutTransition
 import android.content.Context
-import android.os.Build
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import android.widget.TextView
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.testutils.ActivityScenarioResetRule
 import androidx.testutils.ResettableActivityScenarioRule
 import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
 import org.junit.ClassRule
 import org.junit.Rule
 import org.junit.Test
@@ -88,35 +83,6 @@
         assertEquals(recyclerView, viewForOverlay.parent)
     }
 
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1)
-    @Test
-    fun providingEmptyLayoutTransitionCallsSuppress() {
-        val emptyLayoutTransition = LayoutTransition()
-        emptyLayoutTransition.setAnimator(LayoutTransition.APPEARING, null)
-        emptyLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, null)
-        emptyLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, null)
-        emptyLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, null)
-        emptyLayoutTransition.setAnimator(4 /*LayoutTransition.Changing*/, null)
-
-        val recyclerView = RecyclerView(activity)
-        @Suppress("DEPRECATION")
-        recyclerView.layoutTransition = emptyLayoutTransition
-
-        assertTrue(recyclerView.isLayoutSuppressed)
-    }
-
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1)
-    @Test
-    fun clearingLayoutTransitionCallsUnsuppress() {
-        val recyclerView = RecyclerView(activity)
-        recyclerView.suppressLayout(true)
-
-        @Suppress("DEPRECATION")
-        recyclerView.layoutTransition = null
-
-        assertFalse(recyclerView.isLayoutSuppressed)
-    }
-
     private class TransitionHolder(context: Context) : RecyclerView.ViewHolder(TextView(context))
 
     private class TestAdapter : RecyclerView.Adapter<TransitionHolder>() {
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/StaggeredGridLayoutManagerTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/StaggeredGridLayoutManagerTest.java
index 7fca165..14d5625 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/StaggeredGridLayoutManagerTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/StaggeredGridLayoutManagerTest.java
@@ -1292,14 +1292,9 @@
         smoothScrollToPosition(mAdapter.getItemCount() / 2);
         final int changePosition = mAdapter.getItemCount() / 4;
         mLayoutManager.expectLayouts(1);
-        if (RecyclerView.POST_UPDATES_ON_ANIMATION) {
-            mAdapter.changeAndNotify(changePosition, 1);
-            mLayoutManager.assertNoLayout("no layout should happen when an invisible child is "
-                    + "updated", 1);
-        } else {
-            mAdapter.changeAndNotify(changePosition, 1);
-            mLayoutManager.waitForLayout(1);
-        }
+        mAdapter.changeAndNotify(changePosition, 1);
+        mLayoutManager.assertNoLayout("no layout should happen when an invisible child is "
+                + "updated", 1);
 
         // delete an item before visible area
         int deletedPosition = mLayoutManager.getPosition(mLayoutManager.getChildAt(0)) - 2;
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
index 7bf62a9..d778033 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
@@ -849,8 +849,7 @@
         if (mPositionTargetedByScrollInDirection != INVALID_POSITION) {
             View viewTargetedByScrollInDirection = findViewByPosition(
                     mPositionTargetedByScrollInDirection);
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
-                    && viewTargetedByScrollInDirection != null) {
+            if (viewTargetedByScrollInDirection != null) {
                 // Send event after the scroll associated with ACTION_SCROLL_IN_DIRECTION (see
                 // performAccessibilityAction()) concludes and layout completes. Accessibility
                 // services can listen for this event and change UI state as needed.
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
index 16d96e4..c144542 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
@@ -245,8 +245,8 @@
      * recursively traverses itemView and invalidates display list for each ViewGroup that matches
      * this criteria.
      */
-    static final boolean FORCE_INVALIDATE_DISPLAY_LIST = Build.VERSION.SDK_INT == 18
-            || Build.VERSION.SDK_INT == 19 || Build.VERSION.SDK_INT == 20;
+    static final boolean FORCE_INVALIDATE_DISPLAY_LIST = Build.VERSION.SDK_INT == 19
+            || Build.VERSION.SDK_INT == 20;
     /**
      * On M+, an unspecified measure spec may include a hint which we can use. On older platforms,
      * this value might be garbage. To save LayoutManagers from it, RecyclerView sets the size to
@@ -254,8 +254,6 @@
      */
     static final boolean ALLOW_SIZE_IN_UNSPECIFIED_SPEC = Build.VERSION.SDK_INT >= 23;
 
-    static final boolean POST_UPDATES_ON_ANIMATION = Build.VERSION.SDK_INT >= 16;
-
     /**
      * On L+, with RenderThread, the UI thread has idle time after it has passed a frame off to
      * RenderThread but before the next frame begins. We schedule prefetch work in this window.
@@ -263,22 +261,6 @@
     static final boolean ALLOW_THREAD_GAP_WORK = Build.VERSION.SDK_INT >= 21;
 
     /**
-     * FocusFinder#findNextFocus is broken on ICS MR1 and older for View.FOCUS_BACKWARD direction.
-     * We convert it to an absolute direction such as FOCUS_DOWN or FOCUS_LEFT.
-     */
-    private static final boolean FORCE_ABS_FOCUS_SEARCH_DIRECTION = Build.VERSION.SDK_INT <= 15;
-
-    /**
-     * on API 15-, a focused child can still be considered a focused child of RV even after
-     * it's being removed or its focusable flag is set to false. This is because when this focused
-     * child is detached, the reference to this child is not removed in clearFocus. API 16 and above
-     * properly handle this case by calling ensureInputFocusOnFirstFocusable or rootViewRequestFocus
-     * to request focus on a new child, which will clear the focus on the old (detached) child as a
-     * side-effect.
-     */
-    private static final boolean IGNORE_DETACHED_FOCUSED_CHILD = Build.VERSION.SDK_INT <= 15;
-
-    /**
      * When flinging the stretch towards scrolling content, it should destretch quicker than the
      * fling would normally do. The visual effect of flinging the stretch looks strange as little
      * appears to happen at first and then when the stretch disappears, the content starts
@@ -2719,26 +2701,6 @@
     @Deprecated
     @Override
     public void setLayoutTransition(LayoutTransition transition) {
-        if (Build.VERSION.SDK_INT < 18) {
-            // Transitions on APIs below 18 are using an empty LayoutTransition as a replacement
-            // for suppressLayout(true) and null LayoutTransition to then unsuppress it.
-            // We can detect this cases and use our suppressLayout() implementation instead.
-            if (transition == null) {
-                suppressLayout(false);
-                return;
-            } else {
-                int layoutTransitionChanging = 4; // LayoutTransition.CHANGING (Added in API 16)
-                if (transition.getAnimator(LayoutTransition.CHANGE_APPEARING) == null
-                        && transition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING) == null
-                        && transition.getAnimator(LayoutTransition.APPEARING) == null
-                        && transition.getAnimator(LayoutTransition.DISAPPEARING) == null
-                        && transition.getAnimator(layoutTransitionChanging) == null) {
-                    suppressLayout(true);
-                    return;
-                }
-            }
-        }
-
         if (transition == null) {
             super.setLayoutTransition(null);
         } else {
@@ -3348,10 +3310,6 @@
                         direction == View.FOCUS_FORWARD ? View.FOCUS_DOWN : View.FOCUS_UP;
                 final View found = ff.findNextFocus(this, focused, absDir);
                 needsFocusFailureLayout = found == null;
-                if (FORCE_ABS_FOCUS_SEARCH_DIRECTION) {
-                    // Workaround for broken FOCUS_BACKWARD in API 15 and older devices.
-                    direction = absDir;
-                }
             }
             if (!needsFocusFailureLayout && mLayout.canScrollHorizontally()) {
                 boolean rtl = mLayout.getLayoutDirection() == ViewCompat.LAYOUT_DIRECTION_RTL;
@@ -3359,10 +3317,6 @@
                         ? View.FOCUS_RIGHT : View.FOCUS_LEFT;
                 final View found = ff.findNextFocus(this, focused, absDir);
                 needsFocusFailureLayout = found == null;
-                if (FORCE_ABS_FOCUS_SEARCH_DIRECTION) {
-                    // Workaround for broken FOCUS_BACKWARD in API 15 and older devices.
-                    direction = absDir;
-                }
             }
             if (needsFocusFailureLayout) {
                 consumePendingUpdateOperations();
@@ -4611,26 +4565,7 @@
         // only recover focus if RV itself has the focus or the focused view is hidden
         if (!isFocused()) {
             final View focusedChild = getFocusedChild();
-            if (IGNORE_DETACHED_FOCUSED_CHILD
-                    && (focusedChild.getParent() == null || !focusedChild.hasFocus())) {
-                // Special handling of API 15-. A focused child can be invalid because mFocus is not
-                // cleared when the child is detached (mParent = null),
-                // This happens because clearFocus on API 15- does not invalidate mFocus of its
-                // parent when this child is detached.
-                // For API 16+, this is not an issue because requestFocus takes care of clearing the
-                // prior detached focused child. For API 15- the problem happens in 2 cases because
-                // clearChild does not call clearChildFocus on RV: 1. setFocusable(false) is called
-                // for the current focused item which calls clearChild or 2. when the prior focused
-                // child is removed, removeDetachedView called in layout step 3 which calls
-                // clearChild. We should ignore this invalid focused child in all our calculations
-                // for the next view to receive focus, and apply the focus recovery logic instead.
-                if (mChildHelper.getChildCount() == 0) {
-                    // No children left. Request focus on the RV itself since one of its children
-                    // was holding focus previously.
-                    requestFocus();
-                    return;
-                }
-            } else if (!mChildHelper.isHidden(focusedChild)) {
+            if (!mChildHelper.isHidden(focusedChild)) {
                 // If the currently focused child is hidden, apply the focus recovery logic.
                 // Otherwise return, i.e. the currently (unhidden) focused child is good enough :/.
                 return;
@@ -6266,7 +6201,7 @@
         }
 
         void triggerUpdateProcessor() {
-            if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
+            if (mHasFixedSize && mIsAttached) {
                 ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
             } else {
                 mAdapterUpdateDuringMeasure = true;
diff --git a/settings.gradle b/settings.gradle
index 0be61e58..b3bdb86 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -513,6 +513,7 @@
 includeProject(":compose:material3:material3-adaptive:material3-adaptive-samples", "compose/material3/material3-adaptive/samples", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-adaptive-navigation-suite", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-adaptive-navigation-suite:material3-adaptive-navigation-suite-samples", "compose/material3/material3-adaptive-navigation-suite/samples", [BuildType.COMPOSE])
+includeProject(":compose:material3:material3-common", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-lint", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-window-size-class", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-window-size-class:material3-window-size-class-samples", "compose/material3/material3-window-size-class/samples", [BuildType.COMPOSE])
diff --git a/tracing/tracing/lint-baseline.xml b/tracing/tracing/lint-baseline.xml
deleted file mode 100644
index 0391a7b..0000000
--- a/tracing/tracing/lint-baseline.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-alpha04" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-alpha04)" variant="all" version="8.3.0-alpha04">
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18 &amp;&amp; Build.VERSION.SDK_INT &lt; 31) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= 18) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 18"
-        errorLine1="@RequiresApi(18)"
-        errorLine2="~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/TraceApi18Impl.java"/>
-    </issue>
-
-</issues>
diff --git a/tracing/tracing/src/main/java/androidx/tracing/Trace.java b/tracing/tracing/src/main/java/androidx/tracing/Trace.java
index 9a7dcba..d2eef10 100644
--- a/tracing/tracing/src/main/java/androidx/tracing/Trace.java
+++ b/tracing/tracing/src/main/java/androidx/tracing/Trace.java
@@ -96,7 +96,7 @@
      * API 31.
      */
     public static void forceEnableAppTracing() {
-        if (Build.VERSION.SDK_INT >= 18 && Build.VERSION.SDK_INT < 31) {
+        if (Build.VERSION.SDK_INT < 31) {
             try {
                 if (!sHasAppTracingEnabled) {
                     sHasAppTracingEnabled = true; // only attempt once
@@ -126,9 +126,7 @@
      * @param label The name of the code section to appear in the trace.
      */
     public static void beginSection(@NonNull String label) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            TraceApi18Impl.beginSection(truncatedTraceSectionLabel(label));
-        }
+        android.os.Trace.beginSection(truncatedTraceSectionLabel(label));
     }
 
     /**
@@ -140,9 +138,7 @@
      * called from the same thread.
      */
     public static void endSection() {
-        if (Build.VERSION.SDK_INT >= 18) {
-            TraceApi18Impl.endSection();
-        }
+        android.os.Trace.endSection();
     }
 
     /**
@@ -215,77 +211,69 @@
         }
     }
 
-    @SuppressWarnings({"JavaReflectionMemberAccess", "ConstantConditions"})
+    @SuppressWarnings({"JavaReflectionMemberAccess", "BanUncheckedReflection"})
     private static boolean isEnabledFallback() {
-        if (Build.VERSION.SDK_INT >= 18) {
-            try {
-                if (sIsTagEnabledMethod == null) {
-                    Field traceTagAppField = android.os.Trace.class.getField("TRACE_TAG_APP");
-                    sTraceTagApp = traceTagAppField.getLong(null);
-                    sIsTagEnabledMethod =
-                            android.os.Trace.class.getMethod("isTagEnabled", long.class);
-                }
-                return (boolean) sIsTagEnabledMethod.invoke(null, sTraceTagApp);
-            } catch (Exception exception) {
-                handleException("isTagEnabled", exception);
+        try {
+            if (sIsTagEnabledMethod == null) {
+                Field traceTagAppField = android.os.Trace.class.getField("TRACE_TAG_APP");
+                sTraceTagApp = traceTagAppField.getLong(null);
+                sIsTagEnabledMethod =
+                        android.os.Trace.class.getMethod("isTagEnabled", long.class);
             }
+            return (boolean) sIsTagEnabledMethod.invoke(null, sTraceTagApp);
+        } catch (Exception exception) {
+            handleException("isTagEnabled", exception);
         }
         // Never enabled on < API 18
         return false;
     }
 
-    @SuppressWarnings("JavaReflectionMemberAccess")
+    @SuppressWarnings({"JavaReflectionMemberAccess", "BanUncheckedReflection"})
     private static void beginAsyncSectionFallback(@NonNull String methodName, int cookie) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            try {
-                if (sAsyncTraceBeginMethod == null) {
-                    sAsyncTraceBeginMethod = android.os.Trace.class.getMethod(
-                            "asyncTraceBegin",
-                            long.class,
-                            String.class, int.class
-                    );
-                }
-                sAsyncTraceBeginMethod.invoke(null, sTraceTagApp, methodName, cookie);
-            } catch (Exception exception) {
-                handleException("asyncTraceBegin", exception);
+        try {
+            if (sAsyncTraceBeginMethod == null) {
+                sAsyncTraceBeginMethod = android.os.Trace.class.getMethod(
+                        "asyncTraceBegin",
+                        long.class,
+                        String.class, int.class
+                );
             }
+            sAsyncTraceBeginMethod.invoke(null, sTraceTagApp, methodName, cookie);
+        } catch (Exception exception) {
+            handleException("asyncTraceBegin", exception);
         }
     }
 
-    @SuppressWarnings("JavaReflectionMemberAccess")
+    @SuppressWarnings({"JavaReflectionMemberAccess", "BanUncheckedReflection"})
     private static void endAsyncSectionFallback(@NonNull String methodName, int cookie) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            try {
-                if (sAsyncTraceEndMethod == null) {
-                    sAsyncTraceEndMethod = android.os.Trace.class.getMethod(
-                            "asyncTraceEnd",
-                            long.class,
-                            String.class, int.class
-                    );
-                }
-                sAsyncTraceEndMethod.invoke(null, sTraceTagApp, methodName, cookie);
-            } catch (Exception exception) {
-                handleException("asyncTraceEnd", exception);
+        try {
+            if (sAsyncTraceEndMethod == null) {
+                sAsyncTraceEndMethod = android.os.Trace.class.getMethod(
+                        "asyncTraceEnd",
+                        long.class,
+                        String.class, int.class
+                );
             }
+            sAsyncTraceEndMethod.invoke(null, sTraceTagApp, methodName, cookie);
+        } catch (Exception exception) {
+            handleException("asyncTraceEnd", exception);
         }
     }
 
-    @SuppressWarnings("JavaReflectionMemberAccess")
+    @SuppressWarnings({"JavaReflectionMemberAccess", "BanUncheckedReflection"})
     private static void setCounterFallback(@NonNull String counterName, int counterValue) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            try {
-                if (sTraceCounterMethod == null) {
-                    sTraceCounterMethod = android.os.Trace.class.getMethod(
-                            "traceCounter",
-                            long.class,
-                            String.class,
-                            int.class
-                    );
-                }
-                sTraceCounterMethod.invoke(null, sTraceTagApp, counterName, counterValue);
-            } catch (Exception exception) {
-                handleException("traceCounter", exception);
+        try {
+            if (sTraceCounterMethod == null) {
+                sTraceCounterMethod = android.os.Trace.class.getMethod(
+                        "traceCounter",
+                        long.class,
+                        String.class,
+                        int.class
+                );
             }
+            sTraceCounterMethod.invoke(null, sTraceTagApp, counterName, counterValue);
+        } catch (Exception exception) {
+            handleException("traceCounter", exception);
         }
     }
 
diff --git a/tracing/tracing/src/main/java/androidx/tracing/TraceApi18Impl.java b/tracing/tracing/src/main/java/androidx/tracing/TraceApi18Impl.java
deleted file mode 100644
index f70646e..0000000
--- a/tracing/tracing/src/main/java/androidx/tracing/TraceApi18Impl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.tracing;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-/**
- * This is a helper class that handles {@link android.os.Trace} functionality in API >= 18.
- * <p>
- * This class is being defined separately to avoid class verification failures.
- * For more information read https://chromium.googlesource
- * .com/chromium/src/build/+/refs/heads/master/android/docs/class_verification_failures
- * .md#understanding-the-reason-for-the-failure
- */
-@RequiresApi(18)
-final class TraceApi18Impl {
-
-    private TraceApi18Impl() {
-        // Does nothing
-    }
-
-    /**
-     * Writes a trace message to indicate that a given section of code has begun. This call must
-     * be followed by a corresponding call to {@link #endSection()} on the same thread.
-     *
-     * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
-     * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
-     * these characters they will be replaced with a space character in the trace.
-     *
-     * @param label The name of the code section to appear in the trace.  This may be at
-     *              most 127 Unicode code units long.
-     */
-    public static void beginSection(@NonNull String label) {
-        android.os.Trace.beginSection(label);
-    }
-
-    /**
-     * Writes a trace message to indicate that a given section of code has ended. This call must
-     * be preceded by a corresponding call to {@link #beginSection(String)}. Calling this method
-     * will mark the end of the most recently begun section of code, so care must be taken to
-     * ensure that beginSection / endSection pairs are properly nested and called from the same
-     * thread.
-     */
-    public static void endSection() {
-        android.os.Trace.endSection();
-    }
-}
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
index 654dae7..423ff64 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/PositionIndicator.kt
@@ -223,8 +223,8 @@
 @Deprecated(
     "This overload is provided for backwards compatibility with " +
         "Compose for Wear OS 1.2." +
-        "A newer overload is available with additional showFadeInAnimation, " +
-        "showFadeOutAnimation and showPositionAnimation parameters.",
+        "A newer overload is available with additional fadeInAnimationSpec, " +
+        "fadeOutAnimationSpec and positionAnimationSpec parameters.",
     level = DeprecationLevel.HIDDEN
 )
 @Composable
@@ -305,8 +305,8 @@
 @Deprecated(
     "This overload is provided for backwards compatibility with " +
         "Compose for Wear OS 1.2." +
-        "A newer overload is available with additional showFadeInAnimation, " +
-        "showFadeOutAnimation and showPositionAnimation parameters.",
+        "A newer overload is available with additional fadeInAnimationSpec, " +
+        "fadeOutAnimationSpec and positionAnimationSpec parameters.",
     level = DeprecationLevel.HIDDEN
 )
 @Composable
@@ -422,8 +422,8 @@
 @Deprecated(
     "This overload is provided for backwards compatibility with " +
         "Compose for Wear OS 1.2." +
-        "A newer overload is available with additional showFadeInAnimation, " +
-        "showFadeOutAnimation and showPositionAnimation parameters.",
+        "A newer overload is available with additional fadeInAnimationSpec, " +
+        "fadeOutAnimationSpec and positionAnimationSpec parameters.",
     level = DeprecationLevel.HIDDEN
 )
 @Composable
@@ -566,8 +566,8 @@
 @Deprecated(
     "This overload is provided for backwards compatibility with " +
         "Compose for Wear OS 1.2." +
-        "A newer overload is available with additional showFadeInAnimation, " +
-        "showFadeOutAnimation and showPositionAnimation parameters.",
+        "A newer overload is available with additional fadeInAnimationSpec, " +
+        "fadeOutAnimationSpec and positionAnimationSpec parameters.",
     level = DeprecationLevel.HIDDEN
 )
 @Composable
@@ -602,16 +602,21 @@
  * dimensions [indicatorHeight] and [indicatorWidth], and position with respect to the edge of the
  * screen according to [paddingHorizontal]
  *
- * This [PositionIndicator] has 3 separate flags to control different animations.
- * - [showFadeInAnimation] - controls fade-in animation.
- * - [showFadeOutAnimation] - controls fade-out animation.
- * - [showPositionAnimation] - controls position change animation.
+ * This [PositionIndicator] has 3 separate animation specs to control different animations.
+ * - [fadeInAnimationSpec] - controls fade-in animation.
+ * - [fadeOutAnimationSpec] - controls fade-out animation.
+ * - [positionAnimationSpec] - controls position change animation.
  *
  * For performance reasons and for UX consistency, when [PositionIndicator] is used with scrollable
- * list, we recommend to switch off [showFadeInAnimation] and [showPositionAnimation] flags.
+ * list, we recommend to switch off fade-in and position animations by passing [snap] spec into
+ * [fadeInAnimationSpec] and [positionAnimationSpec] parameters.
  * If [PositionIndicator] is used as a standalone indicator, for example as volume control,
  * then we recommend to have all 3 animations turned on.
  *
+ * If color of [PositionIndicator] is not white and position animation is enabled - a short
+ * highlight animation will be triggered on any position change.
+ * This is a short animation accenting [PositionIndicator] with white color with 33% opacity.
+ *
  * For more information, see the
  * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
  * guide.
@@ -952,8 +957,8 @@
 @Deprecated(
     "This overload is provided for backwards compatibility with " +
         "Compose for Wear OS 1.2." +
-        "A newer overload is available with additional showFadeInAnimation, " +
-        "showFadeOutAnimation and showPositionAnimation parameters.",
+        "A newer overload is available with additional fadeInAnimationSpec, " +
+        "fadeOutAnimationSpec and positionAnimationSpec parameters.",
     level = DeprecationLevel.HIDDEN
 )
 @Composable
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
index b7de201..1a91267 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Button.kt
@@ -17,25 +17,41 @@
 package androidx.wear.compose.material3
 
 import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.Interaction
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.IntrinsicSize
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.ripple.rememberRipple
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.paint
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.painter.ColorPainter
 import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.Dp
@@ -1188,18 +1204,29 @@
     interactionSource: MutableInteractionSource,
     content: @Composable RowScope.() -> Unit
 ) {
-    androidx.wear.compose.materialcore.Chip(
-        modifier = modifier
+    val borderModifier = if (border != null)
+        modifier.border(
+            border = border,
+            shape = shape
+        ) else modifier
+    Row(
+        modifier = borderModifier
             .defaultMinSize(minHeight = ButtonDefaults.Height)
-            .height(IntrinsicSize.Min),
-        >
-        background = { colors.containerPainter(enabled = it) },
-        border = { rememberUpdatedState(border) },
-        enabled = enabled,
-        contentPadding = contentPadding,
-        shape = shape,
-        interactionSource = interactionSource,
-        role = Role.Button,
+            .height(IntrinsicSize.Min)
+            .clip(shape = shape)
+            .width(intrinsicSize = IntrinsicSize.Max)
+            .paint(
+                painter = colors.containerPainter(enabled = enabled).value,
+                contentScale = ContentScale.Crop
+            )
+            .clickable(
+                enabled = enabled,
+                >
+                role = Role.Button,
+                indication = rememberRipple(),
+                interactionSource = interactionSource,
+            )
+            .padding(contentPadding),
         content = provideScopeContent(
             colors.contentColor(enabled = enabled),
             labelFont,
@@ -1228,31 +1255,48 @@
     interactionSource: MutableInteractionSource,
     label: @Composable RowScope.() -> Unit
 ) {
-    androidx.wear.compose.materialcore.Chip(
-        modifier = modifier
-            .defaultMinSize(minHeight = ButtonDefaults.Height)
-            .height(IntrinsicSize.Min),
+    Button(
         >
-        background = { colors.containerPainter(enabled = it) },
-        border = { rememberUpdatedState(border) },
+        modifier = modifier,
         enabled = enabled,
-        interactionSource = interactionSource,
         shape = shape,
+        labelFont = labelFont,
+        colors = colors,
+        border = border,
         contentPadding = contentPadding,
-        label = provideScopeContent(
-            colors.contentColor(enabled),
-            labelFont,
-            label
-        ),
-        secondaryLabel = secondaryLabel?.let { provideScopeContent(
-            colors.secondaryContentColor(enabled),
-            secondaryLabelFont,
-            secondaryLabel
-        ) },
-        icon = icon?.let {
-            provideScopeContent(colors.iconColor(enabled), icon)
-        },
-        defaultIconSpacing = ButtonDefaults.IconSpacing,
-        role = Role.Button
-    )
+        interactionSource = interactionSource,
+    ) {
+        Row(
+            verticalAlignment = Alignment.CenterVertically,
+            // Fill the container height but not its width as chips have fixed size height but we
+            // want them to be able to fit their content
+            modifier = Modifier.fillMaxHeight()
+        ) {
+            if (icon != null) {
+                Box(
+                    modifier = Modifier.wrapContentSize(align = Alignment.Center),
+                    content = provideScopeContent(colors.iconColor(enabled), icon)
+                )
+                Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
+            }
+            Column {
+                Row(
+                    content = provideScopeContent(
+                        colors.contentColor(enabled),
+                        labelFont,
+                        label
+                    )
+                )
+                secondaryLabel?.let {
+                    Row(
+                        content = provideScopeContent(
+                            colors.secondaryContentColor(enabled),
+                            secondaryLabelFont,
+                            secondaryLabel
+                        )
+                    )
+                }
+            }
+        }
+    }
 }
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ColorBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ColorBuilders.java
index 6b55c675..544b9c8 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ColorBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ColorBuilders.java
@@ -321,7 +321,8 @@
             @NonNull
             Builder setColor(@NonNull ColorProp color) {
                 if (color.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setColor doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "ColorStop.Builder.setColor doesn't support dynamic values.");
                 }
                 mImpl.setColor(color.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -341,7 +342,8 @@
             @NonNull
             Builder setOffset(@NonNull FloatProp offset) {
                 if (offset.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setOffset doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "ColorStop.Builder.setOffset doesn't support dynamic values.");
                 }
                 float value = offset.getValue();
                 if (value < 0f || value > 1f) {
@@ -541,7 +543,7 @@
             public Builder setStartAngle(@NonNull DegreesProp startAngle) {
                 if (startAngle.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setStartAngle doesn't support dynamic values.");
+                            "SweepGradient.Builder.setStartAngle doesn't support dynamic values.");
                 }
                 mImpl.setStartAngle(startAngle.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -566,7 +568,7 @@
             public Builder setEndAngle(@NonNull DegreesProp endAngle) {
                 if (endAngle.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setEndAngle doesn't support dynamic values.");
+                            "SweepGradient.Builder.setEndAngle doesn't support dynamic values.");
                 }
                 mImpl.setEndAngle(endAngle.toProto());
                 mFingerprint.recordPropertyUpdate(
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
index 2fc0e2f..525958a 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
@@ -1032,7 +1032,8 @@
             public Builder setLayoutWeight(@NonNull FloatProp layoutWeight) {
                 if (layoutWeight.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setLayoutWeight doesn't support dynamic values.");
+                            "ExpandedDimensionProp.Builder.setLayoutWeight doesn't support dynamic"
+                                + " values.");
                 }
                 mImpl.setLayoutWeight(layoutWeight.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -1142,7 +1143,8 @@
             public Builder setMinimumSize(@NonNull DpProp minimumSize) {
                 if (minimumSize.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setMinimumSize doesn't support dynamic values.");
+                            "WrappedDimensionProp.Builder.setMinimumSize doesn't support dynamic"
+                                + " values.");
                 }
                 mImpl.setMinimumSize(minimumSize.toProto());
                 mFingerprint.recordPropertyUpdate(
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
index 28eaf27..f353a88 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
@@ -2116,7 +2116,7 @@
             public Builder setResourceId(@NonNull StringProp resourceId) {
                 if (resourceId.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setResourceId doesn't support dynamic values.");
+                            "Image.Builder.setResourceId doesn't support dynamic values.");
                 }
                 mImpl.setResourceId(resourceId.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -3156,7 +3156,7 @@
             public Builder setResourceId(@NonNull StringProp resourceId) {
                 if (resourceId.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setResourceId doesn't support dynamic values.");
+                            "SpanImage.Builder.setResourceId doesn't support dynamic values.");
                 }
                 mImpl.setResourceId(resourceId.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -3185,7 +3185,8 @@
             @NonNull
             public Builder setWidth(@NonNull DpProp width) {
                 if (width.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setWidth doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "SpanImage.Builder.setWidth doesn't support dynamic values.");
                 }
                 mImpl.setWidth(width.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -3203,7 +3204,8 @@
             @NonNull
             public Builder setHeight(@NonNull DpProp height) {
                 if (height.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setHeight doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "SpanImage.Builder.setHeight doesn't support dynamic values.");
                 }
                 mImpl.setHeight(height.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -4530,7 +4532,8 @@
             @NonNull
             public Builder setText(@NonNull StringProp text) {
                 if (text.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setText doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "ArcText.Builder.setText doesn't support dynamic values.");
                 }
                 mImpl.setText(text.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -4813,7 +4816,7 @@
             public Builder setThickness(@NonNull DpProp thickness) {
                 if (thickness.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setThickness doesn't support dynamic values.");
+                            "ArcLine.Builder.setThickness doesn't support dynamic values.");
                 }
                 mImpl.setThickness(thickness.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -5141,7 +5144,8 @@
             @NonNull
             public Builder setLength(@NonNull DegreesProp length) {
                 if (length.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setLength doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "ArcSpacer.Builder.setLength doesn't support dynamic values.");
                 }
                 mImpl.setLength(length.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -5160,7 +5164,7 @@
             public Builder setThickness(@NonNull DpProp thickness) {
                 if (thickness.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setThickness doesn't support dynamic values.");
+                            "ArcSpacer.Builder.setThickness doesn't support dynamic values.");
                 }
                 mImpl.setThickness(thickness.toProto());
                 mFingerprint.recordPropertyUpdate(
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java
index e7be5de..dc5499b 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ModifiersBuilders.java
@@ -480,7 +480,8 @@
             public Builder setMinimumClickableWidth(@NonNull DpProp minimumClickableWidth) {
                 if (minimumClickableWidth.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setMinimumClickableWidth doesn't support dynamic values.");
+                            "Clickable.Builder.setMinimumClickableWidth doesn't support dynamic"
+                                + " values.");
                 }
                 mImpl.setMinimumClickableWidth(minimumClickableWidth.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -505,7 +506,8 @@
             public Builder setMinimumClickableHeight(@NonNull DpProp minimumClickableHeight) {
                 if (minimumClickableHeight.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setMinimumClickableHeight doesn't support dynamic values.");
+                            "Clickable.Builder.setMinimumClickableHeight doesn't support dynamic"
+                                + " values.");
                 }
                 mImpl.setMinimumClickableHeight(minimumClickableHeight.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -857,7 +859,8 @@
             @NonNull
             public Builder setEnd(@NonNull DpProp end) {
                 if (end.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setEnd doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "Padding.Builder.setEnd doesn't support dynamic values.");
                 }
                 mImpl.setEnd(end.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -876,7 +879,8 @@
             @NonNull
             public Builder setStart(@NonNull DpProp start) {
                 if (start.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setStart doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "Padding.Builder.setStart doesn't support dynamic values.");
                 }
                 mImpl.setStart(start.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -894,7 +898,8 @@
             @NonNull
             public Builder setTop(@NonNull DpProp top) {
                 if (top.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setTop doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "Padding.Builder.setTop doesn't support dynamic values.");
                 }
                 mImpl.setTop(top.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -912,7 +917,8 @@
             @NonNull
             public Builder setBottom(@NonNull DpProp bottom) {
                 if (bottom.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setBottom doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "Padding.Builder.setBottom doesn't support dynamic values.");
                 }
                 mImpl.setBottom(bottom.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -1065,7 +1071,8 @@
             @NonNull
             public Builder setWidth(@NonNull DpProp width) {
                 if (width.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setWidth doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "Border.Builder.setWidth doesn't support dynamic values.");
                 }
                 mImpl.setWidth(width.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -1176,7 +1183,8 @@
             @NonNull
             public Builder setRadius(@NonNull DpProp radius) {
                 if (radius.getDynamicValue() != null) {
-                    throw new IllegalArgumentException("setRadius doesn't support dynamic values.");
+                    throw new IllegalArgumentException(
+                            "Corner.Builder.setRadius doesn't support dynamic values.");
                 }
                 mImpl.setRadius(radius.toProto());
                 mFingerprint.recordPropertyUpdate(
@@ -3109,7 +3117,7 @@
             public Builder setBlurRadius(@NonNull DpProp blurRadius) {
                 if (blurRadius.getDynamicValue() != null) {
                     throw new IllegalArgumentException(
-                            "setBlurRadius doesn't support dynamic values.");
+                            "Shadow.Builder.setBlurRadius doesn't support dynamic values.");
                 }
                 mImpl.setBlurRadius(blurRadius.toProto());
                 mFingerprint.recordPropertyUpdate(
diff --git a/window/window-testing/lint-baseline.xml b/window/window-testing/lint-baseline.xml
deleted file mode 100644
index d5df726..0000000
--- a/window/window-testing/lint-baseline.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-alpha04" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-alpha04)" variant="all" version="8.3.0-alpha04">
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/testing/layout/StubWindowMetricsCalculator.kt"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 17"
-        errorLine1="    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/testing/layout/StubWindowMetricsCalculator.kt"/>
-    </issue>
-
-</issues>
diff --git a/window/window-testing/src/androidTest/java/androidx/window/testing/layout/WindowMetricsCalculatorRuleTest.kt b/window/window-testing/src/androidTest/java/androidx/window/testing/layout/WindowMetricsCalculatorRuleTest.kt
index 7ca466f..95bed8b 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/testing/layout/WindowMetricsCalculatorRuleTest.kt
+++ b/window/window-testing/src/androidTest/java/androidx/window/testing/layout/WindowMetricsCalculatorRuleTest.kt
@@ -120,24 +120,6 @@
         }
     }
 
-    // DefaultDisplay width/height used in tests for API16 and lower
-    @Suppress("DEPRECATION")
-    @Test
-    fun testCurrentWindowMetrics_context_matchesDisplayMetrics_16AndBelow() {
-        Utils.assumePlatformAtOrBelow(Build.VERSION_CODES.JELLY_BEAN)
-
-        activityRule.scenario.onActivity { activity ->
-            val calculator = WindowMetricsCalculator.getOrCreate()
-            val wm = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
-            val actual = calculator.computeCurrentWindowMetrics(activity as Context)
-
-            assertEquals(0, actual.bounds.left)
-            assertEquals(0, actual.bounds.top)
-            assertEquals(wm.defaultDisplay.width, actual.bounds.right)
-            assertEquals(wm.defaultDisplay.height, actual.bounds.bottom)
-        }
-    }
-
     @Test
     fun testCurrentWindowMetrics_context_matchesMaximumMetrics() {
         activityRule.scenario.onActivity { activity ->
diff --git a/window/window-testing/src/main/java/androidx/window/testing/layout/StubWindowMetricsCalculator.kt b/window/window-testing/src/main/java/androidx/window/testing/layout/StubWindowMetricsCalculator.kt
index a057f1c..f59e5ae 100644
--- a/window/window-testing/src/main/java/androidx/window/testing/layout/StubWindowMetricsCalculator.kt
+++ b/window/window-testing/src/main/java/androidx/window/testing/layout/StubWindowMetricsCalculator.kt
@@ -21,7 +21,6 @@
 import android.graphics.Point
 import android.graphics.Rect
 import android.os.Build
-import android.view.Display
 import android.view.WindowManager
 import androidx.annotation.RequiresApi
 import androidx.annotation.UiContext
@@ -57,7 +56,7 @@
 
         return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
             Api30Impl.getWindowMetrics(wm)
-        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+        } else {
             val displaySize = Point()
             // We use getRealSize instead of getSize here because:
             //   1) computeCurrentWindowMetrics and computeMaximumWindowMetrics in this class
@@ -66,14 +65,9 @@
             //   2) getRealSize returns the largest region of the display, whereas getSize returns
             //      the current app window. So to stay consistent with class documentation, we use
             //      getRealSize.
-            Api17Impl.getRealSize(wm.defaultDisplay, displaySize)
+            wm.defaultDisplay.getRealSize(displaySize)
             val bounds = Rect(0, 0, displaySize.x, displaySize.y)
             WindowMetrics(bounds)
-        } else {
-            val width = wm.defaultDisplay.width
-            val height = wm.defaultDisplay.height
-            val bounds = Rect(0, 0, width, height)
-            WindowMetrics(bounds)
         }
     }
 
@@ -87,13 +81,4 @@
             return WindowMetrics(windowManager.currentWindowMetrics.bounds)
         }
     }
-
-    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
-    private object Api17Impl {
-        // getRealSize is deprecated but we have this for compatibility with older versions.
-        @Suppress("DEPRECATION")
-        fun getRealSize(display: Display, point: Point) {
-            display.getRealSize(point)
-        }
-    }
 }
diff --git a/window/window/lint-baseline.xml b/window/window/lint-baseline.xml
deleted file mode 100644
index b2b40e7..0000000
--- a/window/window/lint-baseline.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-alpha04" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-alpha04)" variant="all" version="8.3.0-alpha04">
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 17"
-        errorLine1="@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)"
-        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/area/utils/DeviceMetrics.kt"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 17"
-        errorLine1="@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)"
-        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/area/utils/DeviceUtils.kt"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 17"
-        errorLine1="@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)"
-        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/area/utils/DeviceMetricsCompatUtils.kt"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 17"
-        errorLine1="@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)"
-        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/layout/util/DisplayCompatHelper.kt"/>
-    </issue>
-
-    <issue
-        id="ObsoleteSdkInt"
-        message="Unnecessary; SDK_INT is always >= 19"
-        errorLine1="        if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/window/layout/WindowMetricsCalculatorCompat.kt"/>
-    </issue>
-
-</issues>
diff --git a/window/window/src/main/java/androidx/window/area/utils/DeviceMetrics.kt b/window/window/src/main/java/androidx/window/area/utils/DeviceMetrics.kt
index f8bcab0..75a2db6 100644
--- a/window/window/src/main/java/androidx/window/area/utils/DeviceMetrics.kt
+++ b/window/window/src/main/java/androidx/window/area/utils/DeviceMetrics.kt
@@ -16,14 +16,11 @@
 
 package androidx.window.area.utils
 
-import android.os.Build
 import android.util.DisplayMetrics
-import androidx.annotation.RequiresApi
 
 /**
  * Data class holding metrics about a specific device.
  */
-@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
 internal class DeviceMetrics(
     val manufacturer: String,
     val model: String,
diff --git a/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt b/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt
index 44bb3fa..e72194a 100644
--- a/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt
+++ b/window/window/src/main/java/androidx/window/area/utils/DeviceUtils.kt
@@ -16,16 +16,13 @@
 
 package androidx.window.area.utils
 
-import android.os.Build
 import android.util.DisplayMetrics
-import androidx.annotation.RequiresApi
 import java.util.Locale
 
 /**
  * Utility object to provide information about specific devices that may not be available
  * through the extensions API at a certain vendor API level
  */
-@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
 internal object DeviceUtils {
 
     private val deviceList = listOf(DeviceMetrics("google", "pixel fold",
diff --git a/window/window/src/main/java/androidx/window/layout/WindowMetricsCalculatorCompat.kt b/window/window/src/main/java/androidx/window/layout/WindowMetricsCalculatorCompat.kt
index 6b7c4f2..dcf048fa 100644
--- a/window/window/src/main/java/androidx/window/layout/WindowMetricsCalculatorCompat.kt
+++ b/window/window/src/main/java/androidx/window/layout/WindowMetricsCalculatorCompat.kt
@@ -39,7 +39,6 @@
 import androidx.window.layout.util.ContextCompatHelperApi30.currentWindowInsets
 import androidx.window.layout.util.ContextCompatHelperApi30.currentWindowMetrics
 import androidx.window.layout.util.ContextCompatHelperApi30.maximumWindowBounds
-import androidx.window.layout.util.DisplayCompatHelperApi17.getRealSize
 import androidx.window.layout.util.DisplayCompatHelperApi28.safeInsetBottom
 import androidx.window.layout.util.DisplayCompatHelperApi28.safeInsetLeft
 import androidx.window.layout.util.DisplayCompatHelperApi28.safeInsetRight
@@ -230,10 +229,9 @@
         @Suppress("DEPRECATION")
         val currentDisplay = platformWindowManager.defaultDisplay
         val realDisplaySize = Point()
-        // [Display#getRealSize] is deprecated but we have this for
-        // compatibility with older versions
         @Suppress("DEPRECATION")
-        getRealSize(display = currentDisplay, point = realDisplaySize)
+        currentDisplay.getRealSize(realDisplaySize)
+
         if (!isInMultiWindowMode(activity)) {
             // The activity is not in multi-window mode. Check if the addition of the
             // navigation bar size to mAppBounds results in the real display size and if so
@@ -364,26 +362,10 @@
      * @see Display.getRealSize
      */
     @VisibleForTesting
+    @Suppress("DEPRECATION")
     internal fun getRealSizeForDisplay(display: Display): Point {
         val size = Point()
-        if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
-            getRealSize(display, size)
-        } else {
-            try {
-                val getRealSizeMethod = Display::class.java.getDeclaredMethod(
-                    "getRealSize",
-                    Point::class.java
-                )
-                getRealSizeMethod.isAccessible = true
-                getRealSizeMethod.invoke(display, size)
-            } catch (e: NoSuchMethodException) {
-                Log.w(TAG, e)
-            } catch (e: IllegalAccessException) {
-                Log.w(TAG, e)
-            } catch (e: InvocationTargetException) {
-                Log.w(TAG, e)
-            }
-        }
+        display.getRealSize(size)
         return size
     }
 
diff --git a/window/window/src/main/java/androidx/window/layout/util/DisplayCompatHelper.kt b/window/window/src/main/java/androidx/window/layout/util/DisplayCompatHelper.kt
index 09afea5..f99264d 100644
--- a/window/window/src/main/java/androidx/window/layout/util/DisplayCompatHelper.kt
+++ b/window/window/src/main/java/androidx/window/layout/util/DisplayCompatHelper.kt
@@ -16,21 +16,10 @@
 
 package androidx.window.layout.util
 
-import android.graphics.Point
 import android.os.Build
-import android.view.Display
 import android.view.DisplayCutout
 import androidx.annotation.RequiresApi
 
-@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
-internal object DisplayCompatHelperApi17 {
-
-    @Suppress("DEPRECATION")
-    fun getRealSize(display: Display, point: Point) {
-        display.getRealSize(point)
-    }
-}
-
 @RequiresApi(Build.VERSION_CODES.P)
 internal object DisplayCompatHelperApi28 {