7979import java .nio .ByteBuffer ;
8080import java .nio .ByteOrder ;
8181import java .util .ArrayDeque ;
82+ import java .util .Objects ;
8283import java .util .concurrent .Future ;
8384import java .util .concurrent .ScheduledExecutorService ;
8485import org .checkerframework .checker .nullness .qual .EnsuresNonNull ;
@@ -578,7 +579,7 @@ public DefaultAudioSink build() {
578579 @ Nullable private AudioTrack audioTrack ;
579580 private @ MonotonicNonNull AudioCapabilities audioCapabilities ;
580581 private @ MonotonicNonNull AudioCapabilitiesReceiver audioCapabilitiesReceiver ;
581- @ Nullable private OnRoutingChangedListenerApi24 onRoutingChangedListener ;
582+ @ Nullable private OnRoutingChangedListenerBase onRoutingChangedListener ;
582583
583584 private AudioAttributes audioAttributes ;
584585 @ Nullable private MediaPositionParameters afterDrainParameters ;
@@ -909,13 +910,12 @@ private boolean initializeAudioTrack() throws InitializationException {
909910 }
910911 if (preferredDevice != null ) {
911912 audioTrack .setPreferredDevice (preferredDevice );
912- if (audioCapabilitiesReceiver != null ) {
913- audioCapabilitiesReceiver .setRoutedDevice (preferredDevice );
914- }
913+ onRoutingChanged (audioTrack , preferredDevice );
915914 }
916- if (SDK_INT >= 24 && audioCapabilitiesReceiver != null ) {
917- onRoutingChangedListener =
918- new OnRoutingChangedListenerApi24 (audioTrack , audioCapabilitiesReceiver );
915+ if (SDK_INT >= 24 ) {
916+ onRoutingChangedListener = new OnRoutingChangedListenerApi24 (audioTrack );
917+ } else {
918+ onRoutingChangedListener = new OnRoutingChangedListenerApi23 (audioTrack );
919919 }
920920 startMediaTimeUsNeedsInit = true ;
921921
@@ -1624,7 +1624,7 @@ public void flush() {
16241624 pendingConfiguration = null ;
16251625 }
16261626 audioTrackPositionTracker .reset ();
1627- if (SDK_INT >= 24 && onRoutingChangedListener != null ) {
1627+ if (onRoutingChangedListener != null ) {
16281628 onRoutingChangedListener .release ();
16291629 onRoutingChangedListener = null ;
16301630 }
@@ -2139,24 +2139,76 @@ private static int getDeviceIdFromContext(Context context) {
21392139 : C .INDEX_UNSET ;
21402140 }
21412141
2142- @ RequiresApi (24 )
2143- private static final class OnRoutingChangedListenerApi24 {
2142+ private void onRoutingChanged (AudioTrack audioTrack , AudioDeviceInfo device ) {
2143+ if (listener != null ) {
2144+ listener .onRoutingChanged (audioTrack , device );
2145+ }
2146+ if (audioCapabilitiesReceiver != null ) {
2147+ audioCapabilitiesReceiver .setRoutedDevice (device );
2148+ }
2149+ }
2150+
2151+ private interface OnRoutingChangedListenerBase {
2152+ void release ();
2153+ }
21442154
2155+ private final class OnRoutingChangedListenerApi23 implements OnRoutingChangedListenerBase {
2156+ private final AudioTrack audioTrack ;
2157+ private final Handler playbackThreadHandler ;
2158+
2159+ @ Nullable private AudioTrack .OnRoutingChangedListener listener ;
2160+
2161+ public OnRoutingChangedListenerApi23 (AudioTrack audioTrack ) {
2162+ this .audioTrack = audioTrack ;
2163+ this .listener = this ::onRoutingChanged ;
2164+ playbackThreadHandler = new Handler (Objects .requireNonNull (Looper .myLooper ()));
2165+ audioTrack .addOnRoutingChangedListener (listener , playbackThreadHandler );
2166+ }
2167+
2168+ @ Override
2169+ public void release () {
2170+ audioTrack .removeOnRoutingChangedListener (checkNotNull (listener ));
2171+ listener = null ;
2172+ }
2173+
2174+ private void onRoutingChanged (AudioTrack router ) {
2175+ if (listener == null ) {
2176+ // Stale event.
2177+ return ;
2178+ }
2179+ BackgroundExecutor .get ()
2180+ .execute (
2181+ () -> {
2182+ @ Nullable AudioDeviceInfo routedDevice = router .getRoutedDevice ();
2183+ if (routedDevice != null ) {
2184+ playbackThreadHandler .post (
2185+ () -> {
2186+ if (listener == null ) {
2187+ // Stale event.
2188+ return ;
2189+ }
2190+ DefaultAudioSink .this .onRoutingChanged (audioTrack , routedDevice );
2191+ });
2192+ }
2193+ });
2194+ }
2195+ }
2196+
2197+ @ RequiresApi (24 )
2198+ private final class OnRoutingChangedListenerApi24 implements OnRoutingChangedListenerBase {
21452199 private final AudioTrack audioTrack ;
2146- private final AudioCapabilitiesReceiver capabilitiesReceiver ;
21472200 private final Handler playbackThreadHandler ;
21482201
21492202 @ Nullable private OnRoutingChangedListener listener ;
21502203
2151- public OnRoutingChangedListenerApi24 (
2152- AudioTrack audioTrack , AudioCapabilitiesReceiver capabilitiesReceiver ) {
2204+ public OnRoutingChangedListenerApi24 (AudioTrack audioTrack ) {
21532205 this .audioTrack = audioTrack ;
2154- this .capabilitiesReceiver = capabilitiesReceiver ;
21552206 this .listener = this ::onRoutingChanged ;
2156- playbackThreadHandler = new Handler (Looper .myLooper ());
2207+ playbackThreadHandler = new Handler (Objects . requireNonNull ( Looper .myLooper () ));
21572208 audioTrack .addOnRoutingChangedListener (listener , playbackThreadHandler );
21582209 }
21592210
2211+ @ Override
21602212 public void release () {
21612213 audioTrack .removeOnRoutingChangedListener (checkNotNull (listener ));
21622214 listener = null ;
@@ -2178,7 +2230,7 @@ private void onRoutingChanged(AudioRouting router) {
21782230 // Stale event.
21792231 return ;
21802232 }
2181- capabilitiesReceiver . setRoutedDevice ( routedDevice );
2233+ DefaultAudioSink . this . onRoutingChanged ( audioTrack , routedDevice );
21822234 });
21832235 }
21842236 });
0 commit comments