@@ -394,10 +394,14 @@ public void run() {
394394 if (audioDeviceCallback != null ) {
395395 am .unregisterAudioDeviceCallback (audioDeviceCallback );
396396 }
397+ if (communicationDeviceListener != null ) {
398+ am .removeOnCommunicationDeviceChangedListener (communicationDeviceListener );
399+ communicationDeviceListener = null ;
400+ }
397401 if (!USE_CONNECTION_SERVICE && sharedInstance == null ) {
398402 if (isBtHeadsetConnected ) {
399- am . stopBluetoothSco ();
400- am . setBluetoothScoOn (false );
403+ vam . stopBluetooth ();
404+ vam . setBluetoothOn (false );
401405 bluetoothScoActive = false ;
402406 bluetoothScoConnecting = false ;
403407 }
@@ -451,6 +455,7 @@ public void onServiceConnected(int profile, BluetoothProfile proxy) {
451455 };
452456
453457 private AudioDeviceCallback audioDeviceCallback ;
458+ private AudioManager .OnCommunicationDeviceChangedListener communicationDeviceListener ;
454459
455460 private BroadcastReceiver receiver = new BroadcastReceiver () {
456461
@@ -462,11 +467,10 @@ public void onReceive(Context context, Intent intent) {
462467 proximityWakelock .release ();
463468 }
464469 if (isHeadsetPlugged ) {
465- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
466470 VoipAudioManager vam = VoipAudioManager .get ();
467471 if (vam .isSpeakerphoneOn ()) {
468472 previousAudioOutput = 0 ;
469- } else if (am . isBluetoothScoOn ()) {
473+ } else if (vam . isBluetoothOn ()) {
470474 previousAudioOutput = 2 ;
471475 } else {
472476 previousAudioOutput = 1 ;
@@ -493,7 +497,7 @@ public void onReceive(Context context, Intent intent) {
493497 FileLog .e ("Bluetooth SCO state updated: " + state );
494498 }
495499 if (state == AudioManager .SCO_AUDIO_STATE_DISCONNECTED && isBtHeadsetConnected ) {
496- if (!btAdapter .isEnabled () || !PermissionRequest .hasPermission (Manifest .permission .BLUETOOTH_CONNECT ) || btAdapter .getProfileConnectionState (BluetoothProfile .HEADSET ) != BluetoothProfile .STATE_CONNECTED ) {
500+ if (Build . VERSION . SDK_INT >= Build . VERSION_CODES . S ? VoipAudioManager . get (). findBluetoothDevice () == null : ( !btAdapter .isEnabled () || !PermissionRequest .hasPermission (Manifest .permission .BLUETOOTH_CONNECT ) || btAdapter .getProfileConnectionState (BluetoothProfile .HEADSET ) != BluetoothProfile .STATE_CONNECTED ) ) {
497501 updateBluetoothHeadsetState (false );
498502 return ;
499503 }
@@ -504,10 +508,9 @@ public void onReceive(Context context, Intent intent) {
504508 fetchBluetoothDeviceName ();
505509 if (needSwitchToBluetoothAfterScoActivates ) {
506510 needSwitchToBluetoothAfterScoActivates = false ;
507- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
508511 VoipAudioManager vam = VoipAudioManager .get ();
509512 vam .setSpeakerphoneOn (false );
510- am . setBluetoothScoOn (true );
513+ vam . setBluetoothOn (true );
511514 }
512515 }
513516 for (VoIPService .StateListener l : stateListeners ) {
@@ -3808,12 +3811,11 @@ public void toggleSpeakerphoneOrShowRouteSheet(Context context, boolean fromOver
38083811 systemCallConnection .setAudioRoute (systemCallConnection .getCallAudioState ().getRoute () == CallAudioState .ROUTE_BLUETOOTH ? CallAudioState .ROUTE_WIRED_OR_EARPIECE : CallAudioState .ROUTE_BLUETOOTH );
38093812 }
38103813 } else if (audioConfigured && !USE_CONNECTION_SERVICE ) {
3811- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
38123814 VoipAudioManager vam = VoipAudioManager .get ();
38133815 if (hasEarpiece ()) {
38143816 vam .setSpeakerphoneOn (!vam .isSpeakerphoneOn ());
38153817 } else {
3816- am . setBluetoothScoOn (! am . isBluetoothScoOn ());
3818+ vam . setBluetoothOn (! vam . isBluetoothOn ());
38173819 }
38183820 vam .isBluetoothAndSpeakerOnAsync ((isBluetoothOn , isSpeakerOn ) -> {
38193821 updateOutputGainControlState ();
@@ -3834,7 +3836,6 @@ public void setAudioOutput(int which) {
38343836 if (BuildVars .LOGS_ENABLED ) {
38353837 FileLog .d ("setAudioOutput " + which );
38363838 }
3837- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
38383839 VoipAudioManager vam = VoipAudioManager .get ();
38393840 if (USE_CONNECTION_SERVICE && systemCallConnection != null ) {
38403841 switch (which ) {
@@ -3854,35 +3855,35 @@ public void setAudioOutput(int which) {
38543855 if (!bluetoothScoActive ) {
38553856 needSwitchToBluetoothAfterScoActivates = true ;
38563857 try {
3857- am . startBluetoothSco ();
3858+ vam . startBluetooth ();
38583859 } catch (Throwable e ) {
38593860 FileLog .e (e );
38603861 }
38613862 } else {
3862- am . setBluetoothScoOn (true );
3863+ vam . setBluetoothOn (true );
38633864 vam .setSpeakerphoneOn (false );
38643865 }
38653866 audioRouteToSet = AUDIO_ROUTE_BLUETOOTH ;
38663867 break ;
38673868 case 1 :
38683869 needSwitchToBluetoothAfterScoActivates = false ;
38693870 if (bluetoothScoActive || bluetoothScoConnecting ) {
3870- am . stopBluetoothSco ();
3871+ vam . stopBluetooth ();
38713872 bluetoothScoActive = false ;
38723873 bluetoothScoConnecting = false ;
38733874 }
38743875 vam .setSpeakerphoneOn (false );
3875- am . setBluetoothScoOn (false );
3876+ vam . setBluetoothOn (false );
38763877 audioRouteToSet = AUDIO_ROUTE_EARPIECE ;
38773878 break ;
38783879 case 0 :
38793880 needSwitchToBluetoothAfterScoActivates = false ;
38803881 if (bluetoothScoActive || bluetoothScoConnecting ) {
3881- am . stopBluetoothSco ();
3882+ vam . stopBluetooth ();
38823883 bluetoothScoActive = false ;
38833884 bluetoothScoConnecting = false ;
38843885 }
3885- am . setBluetoothScoOn (false );
3886+ vam . setBluetoothOn (false );
38863887 vam .setSpeakerphoneOn (true );
38873888 audioRouteToSet = AUDIO_ROUTE_SPEAKER ;
38883889 break ;
@@ -3914,9 +3915,8 @@ public boolean isSpeakerphoneOn() {
39143915 int route = systemCallConnection .getCallAudioState ().getRoute ();
39153916 return hasEarpiece () ? route == CallAudioState .ROUTE_SPEAKER : route == CallAudioState .ROUTE_BLUETOOTH ;
39163917 } else if (audioConfigured && !USE_CONNECTION_SERVICE ) {
3917- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
39183918 VoipAudioManager vam = VoipAudioManager .get ();
3919- return hasEarpiece () ? vam .isSpeakerphoneOn () : am . isBluetoothScoOn ();
3919+ return hasEarpiece () ? vam .isSpeakerphoneOn () : vam . isBluetoothOn ();
39203920 }
39213921 return speakerphoneStateToSet ;
39223922 }
@@ -3937,9 +3937,8 @@ public int getCurrentAudioRoute() {
39373937 return audioRouteToSet ;
39383938 }
39393939 if (audioConfigured ) {
3940- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
39413940 VoipAudioManager vam = VoipAudioManager .get ();
3942- if (am . isBluetoothScoOn ()) {
3941+ if (vam . isBluetoothOn ()) {
39433942 return AUDIO_ROUTE_BLUETOOTH ;
39443943 } else if (vam .isSpeakerphoneOn ()) {
39453944 return AUDIO_ROUTE_SPEAKER ;
@@ -4207,8 +4206,8 @@ public void onDestroy() {
42074206 VoipAudioManager vam = VoipAudioManager .get ();
42084207 if (!USE_CONNECTION_SERVICE ) {
42094208 if (isBtHeadsetConnected || bluetoothScoActive || bluetoothScoConnecting ) {
4210- am . stopBluetoothSco ();
4211- am . setBluetoothScoOn (false );
4209+ vam . stopBluetooth ();
4210+ vam . setBluetoothOn (false );
42124211 vam .setSpeakerphoneOn (false );
42134212 bluetoothScoActive = false ;
42144213 bluetoothScoConnecting = false ;
@@ -4240,6 +4239,10 @@ public void onDestroy() {
42404239 if (audioDeviceCallback != null ) {
42414240 am .unregisterAudioDeviceCallback (audioDeviceCallback );
42424241 }
4242+ if (communicationDeviceListener != null ) {
4243+ am .removeOnCommunicationDeviceChangedListener (communicationDeviceListener );
4244+ communicationDeviceListener = null ;
4245+ }
42434246
42444247 Utilities .globalQueue .postRunnable (() -> {
42454248 if (soundPool != null ) {
@@ -4677,6 +4680,20 @@ public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
46774680 if (audioDeviceCallback != null ) {
46784681 am .registerAudioDeviceCallback (audioDeviceCallback , new Handler (Looper .getMainLooper ()));
46794682 }
4683+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S && communicationDeviceListener == null ) {
4684+ communicationDeviceListener = device -> {
4685+ bluetoothScoConnecting = false ;
4686+ bluetoothScoActive = VoipAudioManager .isBluetoothDevice (device );
4687+ if (bluetoothScoActive ) {
4688+ needSwitchToBluetoothAfterScoActivates = false ;
4689+ currentBluetoothDeviceName = device .getProductName ().toString ();
4690+ }
4691+ for (StateListener l : stateListeners ) {
4692+ l .onAudioSettingsChanged ();
4693+ }
4694+ };
4695+ am .addOnCommunicationDeviceChangedListener (AndroidUtilities ::runOnUIThread , communicationDeviceListener );
4696+ }
46804697 am .registerMediaButtonEventReceiver (new ComponentName (this , VoIPMediaButtonReceiver .class ));
46814698
46824699 checkUpdateBluetoothHeadset ();
@@ -4724,7 +4741,16 @@ private void checkUpdateBluetoothHeadset() {
47244741 try {
47254742 MediaRouter mr = (MediaRouter ) getSystemService (Context .MEDIA_ROUTER_SERVICE );
47264743 AudioManager am = (AudioManager ) getSystemService (Context .AUDIO_SERVICE );
4727- if (Build .VERSION .SDK_INT < 24 ) {
4744+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
4745+ AudioDeviceInfo device = VoipAudioManager .get ().findBluetoothDevice ();
4746+ if (device != null ) {
4747+ currentBluetoothDeviceName = device .getProductName ().toString ();
4748+ }
4749+ updateBluetoothHeadsetState (device != null );
4750+ for (StateListener l : stateListeners ) {
4751+ l .onAudioSettingsChanged ();
4752+ }
4753+ } else if (Build .VERSION .SDK_INT < 24 ) {
47284754 int headsetState = btAdapter .getProfileConnectionState (BluetoothProfile .HEADSET );
47294755 updateBluetoothHeadsetState (headsetState == BluetoothProfile .STATE_CONNECTED );
47304756 for (StateListener l : stateListeners ) {
@@ -4827,7 +4853,7 @@ private void configureDeviceForCall() {
48274853 try {
48284854 if (hasRtmpStream ()) {
48294855 am .setMode (AudioManager .MODE_NORMAL );
4830- am . setBluetoothScoOn (false );
4856+ VoipAudioManager . get (). setBluetoothOn (false );
48314857 AndroidUtilities .runOnUIThread (() -> {
48324858 if (!MediaController .getInstance ().isMessagePaused ()) {
48334859 MediaController .getInstance ().pauseMessage (MediaController .getInstance ().getPlayingMessageObject ());
@@ -4850,26 +4876,26 @@ private void configureDeviceForCall() {
48504876 if (!bluetoothScoActive ) {
48514877 needSwitchToBluetoothAfterScoActivates = true ;
48524878 try {
4853- am . startBluetoothSco ();
4879+ vam . startBluetooth ();
48544880 } catch (Throwable e ) {
48554881 FileLog .e (e );
48564882 }
48574883 } else {
4858- am . setBluetoothScoOn (true );
4884+ vam . setBluetoothOn (true );
48594885 vam .setSpeakerphoneOn (false );
48604886 }
48614887 break ;
48624888 case AUDIO_ROUTE_EARPIECE :
4863- am . setBluetoothScoOn (false );
4889+ vam . setBluetoothOn (false );
48644890 vam .setSpeakerphoneOn (false );
48654891 break ;
48664892 case AUDIO_ROUTE_SPEAKER :
4867- am . setBluetoothScoOn (false );
4893+ vam . setBluetoothOn (false );
48684894 vam .setSpeakerphoneOn (true );
48694895 break ;
48704896 }
48714897 } else if (isBluetoothHeadsetConnected ()) {
4872- am . setBluetoothScoOn (speakerphoneStateToSet );
4898+ vam . setBluetoothOn (speakerphoneStateToSet );
48734899 } else {
48744900 vam .setSpeakerphoneOn (speakerphoneStateToSet );
48754901 if (speakerphoneStateToSet ) {
@@ -4925,9 +4951,8 @@ public void onSensorChanged(SensorEvent event) {
49254951 return ;
49264952 }
49274953 if (event .sensor .getType () == Sensor .TYPE_PROXIMITY ) {
4928- AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
49294954 VoipAudioManager vam = VoipAudioManager .get ();
4930- if (audioRouteToSet != AUDIO_ROUTE_EARPIECE || isHeadsetPlugged || vam .isSpeakerphoneOn () || (isBluetoothHeadsetConnected () && am . isBluetoothScoOn ())) {
4955+ if (audioRouteToSet != AUDIO_ROUTE_EARPIECE || isHeadsetPlugged || vam .isSpeakerphoneOn () || (isBluetoothHeadsetConnected () && vam . isBluetoothOn ())) {
49314956 return ;
49324957 }
49334958 boolean newIsNear = event .values [0 ] < Math .min (event .sensor .getMaximumRange (), 3 );
@@ -4989,14 +5014,15 @@ private void updateBluetoothHeadsetState(boolean connected) {
49895014 }
49905015 isBtHeadsetConnected = connected ;
49915016 final AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
5017+ final VoipAudioManager vam = VoipAudioManager .get ();
49925018 if (connected && !isRinging () && currentState != 0 ) {
49935019 if (bluetoothScoActive ) {
49945020 if (BuildVars .LOGS_ENABLED ) {
49955021 FileLog .d ("SCO already active, setting audio routing" );
49965022 }
49975023 if (!hasRtmpStream ()) {
49985024 am .setSpeakerphoneOn (false );
4999- am . setBluetoothScoOn (true );
5025+ vam . setBluetoothOn (true );
50005026 }
50015027 } else {
50025028 if (BuildVars .LOGS_ENABLED ) {
@@ -5006,7 +5032,7 @@ private void updateBluetoothHeadsetState(boolean connected) {
50065032 needSwitchToBluetoothAfterScoActivates = true ;
50075033 AndroidUtilities .runOnUIThread (() -> {
50085034 try {
5009- am . startBluetoothSco ();
5035+ vam . startBluetooth ();
50105036 } catch (Throwable ignore ) {
50115037
50125038 }
@@ -5017,7 +5043,7 @@ private void updateBluetoothHeadsetState(boolean connected) {
50175043 bluetoothScoActive = false ;
50185044 bluetoothScoConnecting = false ;
50195045
5020- am . setBluetoothScoOn (false );
5046+ vam . setBluetoothOn (false );
50215047 }
50225048 for (StateListener l : stateListeners ) {
50235049 l .onAudioSettingsChanged ();
@@ -5489,8 +5515,7 @@ public void onSignalBarCountChanged(int newCount) {
54895515 }
54905516
54915517 public boolean isBluetoothOn () {
5492- final AudioManager am = (AudioManager ) getSystemService (AUDIO_SERVICE );
5493- return am .isBluetoothScoOn ();
5518+ return VoipAudioManager .get ().isBluetoothOn ();
54945519 }
54955520
54965521 public boolean isBluetoothWillOn () {
0 commit comments