diff options
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 111 |
1 files changed, 56 insertions, 55 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index f54b243038f2..4293d4510ede 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -136,7 +136,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -768,7 +767,7 @@ public class AudioService extends IAudioService.Stub // Register for device connection intent broadcasts. IntentFilter intentFilter = new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); - intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); intentFilter.addAction(Intent.ACTION_DOCK_EVENT); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); @@ -2929,14 +2928,28 @@ public class AudioService extends IAudioService.Stub } public void setBluetoothScoOnInt(boolean on, String eventSource) { + if (DEBUG_DEVICES) { + Log.d(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource); + } if (on) { // do not accept SCO ON if SCO audio is not connected - synchronized(mScoClients) { - if ((mBluetoothHeadset != null) && - (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) - != BluetoothHeadset.STATE_AUDIO_CONNECTED)) { - mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; - return; + synchronized (mScoClients) { + if (mBluetoothHeadset != null) { + if (mBluetoothHeadsetDevice == null) { + BluetoothDevice activeDevice = mBluetoothHeadset.getActiveDevice(); + if (activeDevice != null) { + // setBtScoActiveDevice() might trigger resetBluetoothSco() which + // will call setBluetoothScoOnInt(false, "resetBluetoothSco") + setBtScoActiveDevice(activeDevice); + } + } + if (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + != BluetoothHeadset.STATE_AUDIO_CONNECTED) { + mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; + Log.w(TAG, "setBluetoothScoOnInt(true) failed because " + + mBluetoothHeadsetDevice + " is not in audio connected mode"); + return; + } } } mForcedUseForComm = AudioSystem.FORCE_BT_SCO; @@ -3324,24 +3337,23 @@ public class AudioService extends IAudioService.Stub } } - void setBtScoDeviceConnectionState(BluetoothDevice btDevice, int state) { + private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) { if (btDevice == null) { - return; + return true; } - String address = btDevice.getAddress(); BluetoothClass btClass = btDevice.getBluetoothClass(); int outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; if (btClass != null) { switch (btClass.getDeviceClass()) { - case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: - case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: - outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; - break; - case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: - outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; - break; + case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: + case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: + outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; + break; + case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: + outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; + break; } } @@ -3349,34 +3361,33 @@ public class AudioService extends IAudioService.Stub address = ""; } - boolean connected = (state == BluetoothProfile.STATE_CONNECTED); - String btDeviceName = btDevice.getName(); - boolean success = - handleDeviceConnection(connected, outDevice, address, btDeviceName) && - handleDeviceConnection(connected, inDevice, address, btDeviceName); - - if (!success) { - return; - } + boolean result = handleDeviceConnection(isActive, outDevice, address, btDeviceName); + // handleDeviceConnection() && result to make sure the method get executed + result = handleDeviceConnection(isActive, inDevice, address, btDeviceName) && result; + return result; + } - /* When one BT headset is disconnected while another BT headset - * is connected, don't mess with the headset device. - */ - if ((state == BluetoothProfile.STATE_DISCONNECTED || - state == BluetoothProfile.STATE_DISCONNECTING) && - mBluetoothHeadset != null && - mBluetoothHeadset.getAudioState(btDevice) == BluetoothHeadset.STATE_AUDIO_CONNECTED) { - Log.w(TAG, "SCO connected through another device, returning"); - return; + void setBtScoActiveDevice(BluetoothDevice btDevice) { + if (DEBUG_DEVICES) { + Log.d(TAG, "setBtScoActiveDevice(" + btDevice + ")"); } - synchronized (mScoClients) { - if (connected) { + final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice; + if (!Objects.equals(btDevice, previousActiveDevice)) { + if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) { + Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device " + + previousActiveDevice); + } + if (!handleBtScoActiveDeviceChange(btDevice, true)) { + Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice); + // set mBluetoothHeadsetDevice to null when failing to add new device + btDevice = null; + } mBluetoothHeadsetDevice = btDevice; - } else { - mBluetoothHeadsetDevice = null; - resetBluetoothSco(); + if (mBluetoothHeadsetDevice == null) { + resetBluetoothSco(); + } } } } @@ -3431,12 +3442,7 @@ public class AudioService extends IAudioService.Stub // Discard timeout message mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); mBluetoothHeadset = (BluetoothHeadset) proxy; - deviceList = mBluetoothHeadset.getConnectedDevices(); - if (deviceList.size() > 0) { - mBluetoothHeadsetDevice = deviceList.get(0); - } else { - mBluetoothHeadsetDevice = null; - } + setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice()); // Refresh SCO audio state checkScoAudioState(); // Continue pending action if any @@ -3557,10 +3563,7 @@ public class AudioService extends IAudioService.Stub void disconnectHeadset() { synchronized (mScoClients) { - if (mBluetoothHeadsetDevice != null) { - setBtScoDeviceConnectionState(mBluetoothHeadsetDevice, - BluetoothProfile.STATE_DISCONNECTED); - } + setBtScoActiveDevice(null); mBluetoothHeadset = null; } } @@ -5732,11 +5735,9 @@ public class AudioService extends IAudioService.Stub AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); } mDockState = dockState; - } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { - state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, - BluetoothProfile.STATE_DISCONNECTED); + } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) { BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - setBtScoDeviceConnectionState(btDevice, state); + setBtScoActiveDevice(btDevice); } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { boolean broadcast = false; int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; |