Skip to content

Commit d107936

Browse files
toniheicopybara-github
authored andcommitted
Add ExoPlayer.setVirtualDeviceId
This allows to dynamically override the virtual device id after the player is created. The initial value is obtained from the Context passed to the player. PiperOrigin-RevId: 819770420
1 parent f4dbb97 commit d107936

File tree

12 files changed

+111
-2
lines changed

12 files changed

+111
-2
lines changed

RELEASENOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
* Enable wake lock handling by default to fix issues with buffering during
4141
background playback. This is equivalent to setting
4242
`ExoPlayer.Builder.setWakeMode` to `C.WAKE_MODE_LOCAL`.
43+
* Add `ExoPlayer.setVirtualDeviceId` to update the virtual device ID
44+
originally obtained from the `Context` passed to `ExoPlayer.Builder`.
4345
* Ensure renderers don't consume data from the next playlist item more
4446
than 10 seconds before the end of the current item.
4547
* Add `setSeekBackIncrementMs`, `setSeekForwardIncrementMs` and

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.google.common.base.Preconditions.checkNotNull;
2222
import static com.google.common.base.Preconditions.checkState;
2323

24+
import android.companion.virtual.VirtualDevice;
2425
import android.content.Context;
2526
import android.media.AudioDeviceInfo;
2627
import android.media.AudioTrack;
@@ -1597,6 +1598,18 @@ void setMediaSources(
15971598
@UnstableApi
15981599
void setPreferredAudioDevice(@Nullable AudioDeviceInfo audioDeviceInfo);
15991600

1601+
/**
1602+
* Sets the virtual device id to be used for playback.
1603+
*
1604+
* <p>Note that the initial value is obtained from {@link Context#getDeviceId()} from the {@link
1605+
* Context} passed to {@link Builder#Builder(Context)}.
1606+
*
1607+
* @param virtualDeviceId The {@linkplain VirtualDevice#getDeviceId() virtual device id}, or
1608+
* {@link C#INDEX_UNSET} if unspecified.
1609+
*/
1610+
@UnstableApi
1611+
void setVirtualDeviceId(int virtualDeviceId);
1612+
16001613
/**
16011614
* Sets whether skipping silences in the audio stream is enabled.
16021615
*

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import static androidx.media3.exoplayer.Renderer.MSG_SET_SKIP_SILENCE_ENABLED;
3535
import static androidx.media3.exoplayer.Renderer.MSG_SET_VIDEO_EFFECTS;
3636
import static androidx.media3.exoplayer.Renderer.MSG_SET_VIDEO_OUTPUT_RESOLUTION;
37+
import static androidx.media3.exoplayer.Renderer.MSG_SET_VIRTUAL_DEVICE_ID;
3738
import static com.google.common.base.Preconditions.checkArgument;
3839
import static com.google.common.base.Preconditions.checkNotNull;
3940
import static com.google.common.base.Preconditions.checkState;
@@ -1612,6 +1613,12 @@ public void setPreferredAudioDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
16121613
sendRendererMessage(TRACK_TYPE_AUDIO, MSG_SET_PREFERRED_AUDIO_DEVICE, audioDeviceInfo);
16131614
}
16141615

1616+
@Override
1617+
public void setVirtualDeviceId(int virtualDeviceId) {
1618+
verifyApplicationThread();
1619+
sendRendererMessage(TRACK_TYPE_AUDIO, MSG_SET_VIRTUAL_DEVICE_ID, virtualDeviceId);
1620+
}
1621+
16151622
@Override
16161623
public void setVolume(float volume) {
16171624
verifyApplicationThread();

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/Renderer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,13 @@ interface WakeupListener {
372372
*/
373373
int MSG_SET_SCRUBBING_MODE = 18;
374374

375+
/**
376+
* The type of a message that can be passed to audio renderers via {@link
377+
* ExoPlayer#createMessage(PlayerMessage.Target)}. The message payload should be an {@link
378+
* Integer} instance representing the virtual device id, or {@link C#INDEX_UNSET} if unspecified.
379+
*/
380+
int MSG_SET_VIRTUAL_DEVICE_ID = 19;
381+
375382
/**
376383
* Applications or extensions may define custom {@code MSG_*} constants that can be passed to
377384
* renderers. These custom constants must be greater than or equal to this value.

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,12 @@ public void setPreferredAudioDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
590590
player.setPreferredAudioDevice(audioDeviceInfo);
591591
}
592592

593+
@Override
594+
public void setVirtualDeviceId(int virtualDeviceId) {
595+
blockUntilConstructorFinished();
596+
player.setVirtualDeviceId(virtualDeviceId);
597+
}
598+
593599
@Override
594600
public void setVolume(float volume) {
595601
blockUntilConstructorFinished();

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioSink.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static java.lang.annotation.ElementType.TYPE_USE;
1919

20+
import android.companion.virtual.VirtualDevice;
2021
import android.media.AudioDeviceInfo;
2122
import android.media.AudioTrack;
2223
import androidx.annotation.IntDef;
@@ -604,6 +605,14 @@ boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAcce
604605
*/
605606
default void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {}
606607

608+
/**
609+
* Sets the virtual device id.
610+
*
611+
* @param virtualDeviceId The {@linkplain VirtualDevice#getDeviceId() virtual device id}, or
612+
* {@link C#INDEX_UNSET} if unspecified.
613+
*/
614+
default void setVirtualDeviceId(int virtualDeviceId) {}
615+
607616
/**
608617
* Sets the offset that is added to the media timestamp before it is passed as {@code
609618
* presentationTimeUs} in {@link #handleBuffer(ByteBuffer, long, int)}.

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
* <li>Message with type {@link #MSG_SET_AUX_EFFECT_INFO} to set the auxiliary effect. The message
8585
* payload should be an {@link AuxEffectInfo} instance that will configure the underlying
8686
* audio track.
87+
* <li>Message with type {@link #MSG_SET_PREFERRED_AUDIO_DEVICE} to set the preferred audio output
88+
* device. The message payload should be an {@link AudioDeviceInfo} instance.
89+
* <li>Message with type {@link #MSG_SET_VIRTUAL_DEVICE_ID} to set the virtual device id. The
90+
* message payload should be an {@link Integer} for the virtual device id or {@link
91+
* C#INDEX_UNSET} if unspecified.
8792
* <li>Message with type {@link #MSG_SET_SKIP_SILENCE_ENABLED} to enable or disable skipping
8893
* silences. The message payload should be a {@link Boolean}.
8994
* <li>Message with type {@link #MSG_SET_AUDIO_SESSION_ID} to set the audio session ID. The
@@ -760,6 +765,9 @@ public void handleMessage(@MessageType int messageType, @Nullable Object message
760765
case MSG_SET_PREFERRED_AUDIO_DEVICE:
761766
audioSink.setPreferredDevice((AudioDeviceInfo) message);
762767
break;
768+
case MSG_SET_VIRTUAL_DEVICE_ID:
769+
audioSink.setVirtualDeviceId((Integer) checkNotNull(message));
770+
break;
763771
case MSG_SET_CAMERA_MOTION_LISTENER:
764772
case MSG_SET_CHANGE_FRAME_RATE_STRATEGY:
765773
case MSG_SET_SCALING_MODE:

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,6 @@ public DefaultAudioSink build() {
508508
initializationExceptionPendingExceptionHolder;
509509
private final PendingExceptionHolder<WriteException> writeExceptionPendingExceptionHolder;
510510
@Nullable private final AudioOffloadListener audioOffloadListener;
511-
private final int virtualDeviceId;
512511

513512
@Nullable private PlayerId playerId;
514513
@Nullable private Listener listener;
@@ -547,6 +546,7 @@ public DefaultAudioSink build() {
547546
private boolean pendingAudioSessionIdChangeConfirmation;
548547
private AuxEffectInfo auxEffectInfo;
549548
@Nullable private AudioDeviceInfo preferredDevice;
549+
private int virtualDeviceId;
550550
private boolean tunneling;
551551
private long lastFeedElapsedRealtimeMs;
552552
private boolean offloadDisabledUntilNextConfiguration;
@@ -1296,6 +1296,16 @@ public void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
12961296
}
12971297
}
12981298

1299+
@Override
1300+
public void setVirtualDeviceId(int virtualDeviceId) {
1301+
virtualDeviceId = resolveDefaultVirtualDeviceIds(virtualDeviceId);
1302+
if (this.virtualDeviceId == virtualDeviceId) {
1303+
return;
1304+
}
1305+
this.virtualDeviceId = virtualDeviceId;
1306+
reconfigureAndFlush();
1307+
}
1308+
12991309
@Override
13001310
public long getAudioTrackBufferSizeUs() {
13011311
if (!isAudioOutputInitialized()) {
@@ -1763,7 +1773,10 @@ private static boolean hasPendingAudioOutputReleases() {
17631773

17641774
@RequiresApi(34)
17651775
private static int getDeviceIdFromContext(Context context) {
1766-
int deviceId = context.getDeviceId();
1776+
return resolveDefaultVirtualDeviceIds(context.getDeviceId());
1777+
}
1778+
1779+
private static int resolveDefaultVirtualDeviceIds(int deviceId) {
17671780
return deviceId != Context.DEVICE_ID_DEFAULT && deviceId != Context.DEVICE_ID_INVALID
17681781
? deviceId
17691782
: C.INDEX_UNSET;

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/ForwardingAudioSink.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ public void setPreferredDevice(@Nullable AudioDeviceInfo audioDeviceInfo) {
156156
sink.setPreferredDevice(audioDeviceInfo);
157157
}
158158

159+
@Override
160+
public void setVirtualDeviceId(int virtualDeviceId) {
161+
sink.setVirtualDeviceId(virtualDeviceId);
162+
}
163+
159164
@Override
160165
public void setOutputStreamOffsetUs(long outputStreamOffsetUs) {
161166
sink.setOutputStreamOffsetUs(outputStreamOffsetUs);

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
* audio track.
9393
* <li>Message with type {@link #MSG_SET_PREFERRED_AUDIO_DEVICE} to set the preferred audio output
9494
* device. The message payload should be an {@link AudioDeviceInfo} instance.
95+
* <li>Message with type {@link #MSG_SET_VIRTUAL_DEVICE_ID} to set the virtual device id. The
96+
* message payload should be an {@link Integer} for the virtual device id or {@link
97+
* C#INDEX_UNSET} if unspecified.
9598
* <li>Message with type {@link #MSG_SET_SKIP_SILENCE_ENABLED} to enable or disable skipping
9699
* silences. The message payload should be a {@link Boolean}.
97100
* <li>Message with type {@link #MSG_SET_AUDIO_SESSION_ID} to set the audio session ID. The
@@ -930,6 +933,9 @@ public void handleMessage(@MessageType int messageType, @Nullable Object message
930933
case MSG_SET_PREFERRED_AUDIO_DEVICE:
931934
audioSink.setPreferredDevice((AudioDeviceInfo) message);
932935
break;
936+
case MSG_SET_VIRTUAL_DEVICE_ID:
937+
audioSink.setVirtualDeviceId((Integer) checkNotNull(message));
938+
break;
933939
case MSG_SET_SKIP_SILENCE_ENABLED:
934940
audioSink.setSkipSilenceEnabled((Boolean) checkNotNull(message));
935941
break;

0 commit comments

Comments
 (0)