@@ -1775,107 +1775,71 @@ public void updateAudioDeviceState() {
1775
1775
// Update the set of available audio devices.
1776
1776
Set <AudioDevice > newAudioDevices = new HashSet <>();
1777
1777
1778
+ // always assume device has speaker phone
1779
+ newAudioDevices .add (AudioDevice .SPEAKER_PHONE );
1780
+
1778
1781
if (bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTED
1779
1782
|| bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTING
1780
1783
|| bluetoothManager .getState () == AppRTCBluetoothManager .State .HEADSET_AVAILABLE ) {
1781
1784
newAudioDevices .add (AudioDevice .BLUETOOTH );
1782
1785
}
1783
1786
1784
1787
if (hasWiredHeadset ) {
1785
- // If a wired headset is connected, then it is the only possible option.
1786
1788
newAudioDevices .add (AudioDevice .WIRED_HEADSET );
1787
- } else {
1788
- // No wired headset, hence the audio-device list can contain speaker
1789
- // phone (on a tablet), or speaker phone and earpiece (on mobile phone).
1790
- newAudioDevices .add (AudioDevice .SPEAKER_PHONE );
1791
- if (hasEarpiece ()) {
1792
- newAudioDevices .add (AudioDevice .EARPIECE );
1793
- }
1794
1789
}
1790
+
1791
+ if (hasEarpiece ()) {
1792
+ newAudioDevices .add (AudioDevice .EARPIECE );
1793
+ }
1794
+
1795
+ // --- check whether user selected audio device is available
1796
+ if (userSelectedAudioDevice != null
1797
+ && userSelectedAudioDevice != AudioDevice .NONE
1798
+ && !newAudioDevices .contains (userSelectedAudioDevice )) {
1799
+ userSelectedAudioDevice = AudioDevice .NONE ;
1800
+ }
1801
+
1795
1802
// Store state which is set to true if the device list has changed.
1796
1803
boolean audioDeviceSetUpdated = !audioDevices .equals (newAudioDevices );
1797
1804
// Update the existing audio device set.
1798
1805
audioDevices = newAudioDevices ;
1799
- // Correct user selected audio devices if needed.
1800
- if (bluetoothManager .getState () == AppRTCBluetoothManager .State .HEADSET_UNAVAILABLE
1801
- && userSelectedAudioDevice == AudioDevice .BLUETOOTH ) {
1802
- // If BT is not available, it can't be the user selection.
1803
- userSelectedAudioDevice = AudioDevice .NONE ;
1804
- }
1805
- if (hasWiredHeadset && userSelectedAudioDevice == AudioDevice .SPEAKER_PHONE ) {
1806
- // If user selected speaker phone, but then plugged wired headset then make
1807
- // wired headset as user selected device.
1808
- userSelectedAudioDevice = AudioDevice .WIRED_HEADSET ;
1809
- }
1810
- if (!hasWiredHeadset && userSelectedAudioDevice == AudioDevice .WIRED_HEADSET ) {
1811
- // If user selected wired headset, but then unplugged wired headset then make
1812
- // speaker phone as user selected device.
1813
- userSelectedAudioDevice = AudioDevice .SPEAKER_PHONE ;
1814
- }
1815
1806
1816
- // Need to start Bluetooth if it is available and user either selected it explicitly or
1817
- // user did not select any output device.
1818
- boolean needBluetoothAudioStart =
1819
- bluetoothManager .getState () == AppRTCBluetoothManager .State .HEADSET_AVAILABLE
1820
- && (userSelectedAudioDevice == AudioDevice .NONE
1821
- || userSelectedAudioDevice == AudioDevice .BLUETOOTH );
1807
+ AudioDevice newAudioDevice = getPreferredAudioDevice ();
1822
1808
1823
- // Need to stop Bluetooth audio if user selected different device and
1824
- // Bluetooth SCO connection is established or in the process.
1825
- boolean needBluetoothAudioStop =
1826
- (bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTED
1827
- || bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTING )
1828
- && (userSelectedAudioDevice != AudioDevice .NONE
1829
- && userSelectedAudioDevice != AudioDevice .BLUETOOTH );
1830
-
1831
- if (bluetoothManager .getState () == AppRTCBluetoothManager .State .HEADSET_AVAILABLE
1832
- || bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTING
1833
- || bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTED ) {
1834
- Log .d (TAG , "Need BT audio: start=" + needBluetoothAudioStart + ", "
1835
- + "stop=" + needBluetoothAudioStop + ", "
1836
- + "BT state=" + bluetoothManager .getState ());
1837
- }
1838
-
1839
- // Start or stop Bluetooth SCO connection given states set earlier.
1840
- if (needBluetoothAudioStop ) {
1809
+ // --- stop bluetooth if needed
1810
+ if (selectedAudioDevice == AudioDevice .BLUETOOTH
1811
+ && newAudioDevice != AudioDevice .BLUETOOTH
1812
+ && (bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTED
1813
+ || bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTING )
1814
+ ) {
1841
1815
bluetoothManager .stopScoAudio ();
1842
1816
bluetoothManager .updateDevice ();
1843
1817
}
1844
1818
1845
- if (needBluetoothAudioStart && !needBluetoothAudioStop ) {
1819
+ // --- start bluetooth if needed
1820
+ if (selectedAudioDevice != AudioDevice .BLUETOOTH
1821
+ && newAudioDevice == AudioDevice .BLUETOOTH
1822
+ && bluetoothManager .getState () == AppRTCBluetoothManager .State .HEADSET_AVAILABLE ) {
1846
1823
// Attempt to start Bluetooth SCO audio (takes a few second to start).
1847
1824
if (!bluetoothManager .startScoAudio ()) {
1848
1825
// Remove BLUETOOTH from list of available devices since SCO failed.
1849
1826
audioDevices .remove (AudioDevice .BLUETOOTH );
1850
1827
audioDeviceSetUpdated = true ;
1828
+ if (userSelectedAudioDevice == AudioDevice .BLUETOOTH ) {
1829
+ userSelectedAudioDevice = AudioDevice .NONE ;
1830
+ }
1831
+ newAudioDevice = getPreferredAudioDevice ();
1851
1832
}
1852
1833
}
1853
-
1854
- // Update selected audio device.
1855
- final AudioDevice newAudioDevice ;
1856
-
1857
- if (bluetoothManager .getState () == AppRTCBluetoothManager .State .SCO_CONNECTED ) {
1858
- // If a Bluetooth is connected, then it should be used as output audio
1859
- // device. Note that it is not sufficient that a headset is available;
1860
- // an active SCO channel must also be up and running.
1861
- newAudioDevice = AudioDevice .BLUETOOTH ;
1862
- } else if (hasWiredHeadset ) {
1863
- // If a wired headset is connected, but Bluetooth is not, then wired headset is used as
1864
- // audio device.
1865
- newAudioDevice = AudioDevice .WIRED_HEADSET ;
1866
- } else if (userSelectedAudioDevice != null
1867
- && userSelectedAudioDevice != AudioDevice .NONE
1868
- && userSelectedAudioDevice != defaultAudioDevice ) {
1869
- newAudioDevice = userSelectedAudioDevice ;
1870
- } else {
1871
- // No wired headset and no Bluetooth, hence the audio-device list can contain speaker
1872
- // phone (on a tablet), or speaker phone and earpiece (on mobile phone).
1873
- // |defaultAudioDevice| contains either AudioDevice.SPEAKER_PHONE or AudioDevice.EARPIECE
1874
- // depending on the user's selgection.
1875
- newAudioDevice = defaultAudioDevice ;
1834
+
1835
+ if (newAudioDevice == AudioDevice .BLUETOOTH
1836
+ && bluetoothManager .getState () != AppRTCBluetoothManager .State .SCO_CONNECTED ) {
1837
+ newAudioDevice = getPreferredAudioDevice (true ); // --- skip bluetooth
1876
1838
}
1839
+
1877
1840
// Switch to new device but only if there has been any changes.
1878
1841
if (newAudioDevice != selectedAudioDevice || audioDeviceSetUpdated ) {
1842
+
1879
1843
// Do the required device switch.
1880
1844
setAudioDeviceInternal (newAudioDevice );
1881
1845
Log .d (TAG , "New device status: "
@@ -1910,4 +1874,31 @@ private WritableMap getAudioDeviceStatusMap() {
1910
1874
1911
1875
return data ;
1912
1876
}
1877
+
1878
+ private AudioDevice getPreferredAudioDevice () {
1879
+ return getPreferredAudioDevice (false );
1880
+ }
1881
+
1882
+ private AudioDevice getPreferredAudioDevice (boolean skipBluetooth ) {
1883
+ final AudioDevice newAudioDevice ;
1884
+
1885
+ if (userSelectedAudioDevice != null && userSelectedAudioDevice != AudioDevice .NONE ) {
1886
+ newAudioDevice = userSelectedAudioDevice ;
1887
+ } else if (!skipBluetooth && audioDevices .contains (AudioDevice .BLUETOOTH )) {
1888
+ // If a Bluetooth is connected, then it should be used as output audio
1889
+ // device. Note that it is not sufficient that a headset is available;
1890
+ // an active SCO channel must also be up and running.
1891
+ newAudioDevice = AudioDevice .BLUETOOTH ;
1892
+ } else if (audioDevices .contains (AudioDevice .WIRED_HEADSET )) {
1893
+ // If a wired headset is connected, but Bluetooth is not, then wired headset is used as
1894
+ // audio device.
1895
+ newAudioDevice = AudioDevice .WIRED_HEADSET ;
1896
+ } else if (audioDevices .contains (defaultAudioDevice )) {
1897
+ newAudioDevice = defaultAudioDevice ;
1898
+ } else {
1899
+ newAudioDevice = AudioDevice .SPEAKER_PHONE ;
1900
+ }
1901
+
1902
+ return newAudioDevice ;
1903
+ }
1913
1904
}
0 commit comments