androidx / androidx/media

Out-of-order command execution in MediaController if Android 12(L) workaround has to kick in

Open
#3,278 1 comment 0 reactions 1 assignee View on GitHub

@marcbaechinger is already working on this.

Since Jun 18, 2026.

bug needs triage
Dominant language
Java
Stars
3k
Forks
955
Avg merge
12d 14h
Merged PRs (30d)
2

Description

Version

Media3 main branch

More version details

cb5ee435c1efe4d7101a677c9bc1b69ec66c832d

Devices that reproduce the issue

SDK 31/32 emulator

Devices that do not reproduce the issue

Only Android 12 / 12L are affected, so it can't be reproduced on SDK 33 emulator for example

Reproducible in the demo app?

Yes

Reproduction steps

Apply the following diff and run the MediaSessionServiceWithNonMainApplicationThreadTest.play_playCalledOnAppThread() test, it will fail.

diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceWithNonMainApplicationThreadTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceWithNonMainApplicationThreadTest.java
index 855e44ef0b..a30702d014 100644
--- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceWithNonMainApplicationThreadTest.java
+++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceWithNonMainApplicationThreadTest.java
@@ -25,6 +25,7 @@ import android.app.ForegroundServiceStartNotAllowedException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import androidx.media3.common.C;
@@ -94,6 +95,7 @@ public class MediaSessionServiceWithNonMainApplicationThreadTest {
     Looper appLooper = appThread.getLooper();
 
     SettableFuture<Looper> playFuture = SettableFuture.create();
+    SettableFuture<Void> setVolumeWasCalled = SettableFuture.create();
     testServiceRegistry.setOnGetSessionHandler(
         controllerInfo -> {
           ExoPlayer exoPlayer =
@@ -107,6 +109,17 @@ public class MediaSessionServiceWithNonMainApplicationThreadTest {
                 public void play() {
                   playFuture.set(Looper.myLooper());
                 }
+
+                @Override
+                public void setVolume(float volume) {
+                  // Must be already done as setVolume() is called after play() on the controller.
+                  try {
+                    assertThat(playFuture.get(0, MILLISECONDS)).isNotNull();
+                  } catch (Exception e) {
+                    throw new RuntimeException(e);
+                  }
+                  setVolumeWasCalled.set(null);
+                }
               };
           return new MediaSession.Builder(context, player)
               .setCallback(
@@ -133,9 +146,13 @@ public class MediaSessionServiceWithNonMainApplicationThreadTest {
     RemoteMediaController controller = controllerTestRule.createRemoteController(token);
 
     controller.play();
+    // Send a command after play to assert they are processed in the correct order even if play
+    // takes a moment. See setVolume above.
+    controller.setVolume(0.5f);
 
     // Verify that playback starts on the application looper.
     assertThat(playFuture.get(TIMEOUT_MS, MILLISECONDS)).isEqualTo(appLooper);
+    assertThat(setVolumeWasCalled.get(TIMEOUT_MS, MILLISECONDS)).isEqualTo(null);
     appThread.quitSafely();
   }
Expected result

MediaController forwards commands to Player in the order it recieves them

Actual result

setVolume is called before play

Media

N/A

Bug Report
  • You will email the zip file produced by adb bugreport to android-media-github@google.com after filing this issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.