audio: Restructure A2DP active device change
Make active device change asynchronous. Restructure A2DP active device change API for clarity and speed. Merge active device and device config change handlers. Fix bug for a new A2DP device connection with handleBluetoothA2dpActiveDeviceChange. Bug: 122944517 Test: still needs Bt side using new interface Change-Id: Ia2fa6b2c98ed4452880e8abca4a069b904f8cc68
This commit is contained in:
committed by
Jean-Michel Trivi
parent
75f61c5919
commit
d7c9598a26
@@ -4144,6 +4144,10 @@ public class AudioManager {
|
||||
/**
|
||||
* Indicate A2DP source or sink active device change and eventually suppress
|
||||
* the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
|
||||
* This operation is asynchronous but its execution will still be sequentially scheduled
|
||||
* relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
|
||||
* int, boolean, int)} and
|
||||
* {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
|
||||
* @param device Bluetooth device connected/disconnected
|
||||
* @param state new connection state (BluetoothProfile.STATE_xxx)
|
||||
* @param profile profile for the A2DP device
|
||||
@@ -4157,18 +4161,16 @@ public class AudioManager {
|
||||
* BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
|
||||
* {@hide}
|
||||
*/
|
||||
public int handleBluetoothA2dpActiveDeviceChange(
|
||||
public void handleBluetoothA2dpActiveDeviceChange(
|
||||
BluetoothDevice device, int state, int profile,
|
||||
boolean suppressNoisyIntent, int a2dpVolume) {
|
||||
final IAudioService service = getService();
|
||||
int delay = 0;
|
||||
try {
|
||||
delay = service.handleBluetoothA2dpActiveDeviceChange(device,
|
||||
service.handleBluetoothA2dpActiveDeviceChange(device,
|
||||
state, profile, suppressNoisyIntent, a2dpVolume);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
return delay;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
|
||||
@@ -171,7 +171,7 @@ interface IAudioService {
|
||||
|
||||
void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
|
||||
|
||||
int handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
|
||||
void handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
|
||||
int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
|
||||
|
||||
@UnsupportedAppUsage
|
||||
|
||||
@@ -230,17 +230,13 @@ import java.util.ArrayList;
|
||||
sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
|
||||
}
|
||||
|
||||
/*package*/ int handleBluetoothA2dpActiveDeviceChange(
|
||||
/*package*/ void postBluetoothA2dpDeviceConfigChangeExt(
|
||||
@NonNull BluetoothDevice device,
|
||||
@AudioService.BtProfileConnectionState int state, int profile,
|
||||
boolean suppressNoisyIntent, int a2dpVolume) {
|
||||
// FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
|
||||
// of handleBluetoothA2dpDeviceConfigChange and
|
||||
// setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
|
||||
synchronized (mDeviceStateLock) {
|
||||
return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
|
||||
suppressNoisyIntent, a2dpVolume);
|
||||
}
|
||||
final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
|
||||
suppressNoisyIntent, a2dpVolume);
|
||||
sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, info);
|
||||
}
|
||||
|
||||
private static final class HearingAidDeviceConnectionInfo {
|
||||
@@ -542,7 +538,8 @@ import java.util.ArrayList;
|
||||
mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
|
||||
}
|
||||
|
||||
/*package*/ void postA2dpActiveDeviceChange(BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
|
||||
/*package*/ void postA2dpActiveDeviceChange(
|
||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
|
||||
sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
|
||||
}
|
||||
|
||||
@@ -714,8 +711,9 @@ import java.util.ArrayList;
|
||||
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
|
||||
synchronized (mDeviceStateLock) {
|
||||
a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
|
||||
mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
|
||||
new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec));
|
||||
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
|
||||
new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
|
||||
BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
|
||||
}
|
||||
break;
|
||||
case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
|
||||
@@ -744,7 +742,8 @@ import java.util.ArrayList;
|
||||
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
|
||||
synchronized (mDeviceStateLock) {
|
||||
mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
|
||||
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj);
|
||||
(BtHelper.BluetoothA2dpDeviceInfo) msg.obj,
|
||||
BtHelper.EVENT_ACTIVE_DEVICE_CHANGE);
|
||||
}
|
||||
break;
|
||||
case MSG_DISCONNECT_A2DP:
|
||||
@@ -816,6 +815,22 @@ import java.util.ArrayList;
|
||||
info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
|
||||
}
|
||||
} break;
|
||||
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT: {
|
||||
final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
|
||||
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
|
||||
"handleBluetoothA2dpActiveDeviceChangeExt "
|
||||
+ " state=" + info.mState
|
||||
// only querying address as this is the only readily available
|
||||
// field on the device
|
||||
+ " addr=" + info.mDevice.getAddress()
|
||||
+ " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
|
||||
+ " vol=" + info.mVolume)).printLog(TAG));
|
||||
synchronized (mDeviceStateLock) {
|
||||
mDeviceInventory.handleBluetoothA2dpActiveDeviceChangeExt(
|
||||
info.mDevice, info.mState, info.mProfile,
|
||||
info.mSupprNoisy, info.mVolume);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
Log.wtf(TAG, "Invalid message " + msg.what);
|
||||
}
|
||||
@@ -863,6 +878,8 @@ import java.util.ArrayList;
|
||||
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
|
||||
// process external command to (dis)connect a hearing aid device
|
||||
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
|
||||
// process external command to (dis)connect or change active A2DP device
|
||||
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT = 29;
|
||||
|
||||
|
||||
private static boolean isMessageHandledUnderWakelock(int msgId) {
|
||||
@@ -877,6 +894,7 @@ import java.util.ArrayList;
|
||||
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
|
||||
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
|
||||
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
|
||||
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -263,74 +263,25 @@ public final class AudioDeviceInventory {
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void onBluetoothA2dpDeviceConfigChange(
|
||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo) {
|
||||
/*package*/ void onBluetoothA2dpActiveDeviceChange(
|
||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
|
||||
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
|
||||
}
|
||||
if (btDevice == null) {
|
||||
return;
|
||||
}
|
||||
String address = btDevice.getAddress();
|
||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||
address = "";
|
||||
}
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"onBluetoothA2dpDeviceConfigChange addr=" + address));
|
||||
|
||||
final int a2dpCodec = btInfo.getCodec();
|
||||
|
||||
synchronized (mConnectedDevices) {
|
||||
if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"A2dp config change ignored"));
|
||||
return;
|
||||
}
|
||||
final String key =
|
||||
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
|
||||
final DeviceInfo di = mConnectedDevices.get(key);
|
||||
if (di == null) {
|
||||
Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpDeviceConfigChange");
|
||||
return;
|
||||
}
|
||||
// Device is connected
|
||||
if (di.mDeviceCodecFormat != a2dpCodec) {
|
||||
di.mDeviceCodecFormat = a2dpCodec;
|
||||
mConnectedDevices.replace(key, di);
|
||||
}
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
Log.d(TAG, "onBluetoothA2dpDeviceConfigChange: codec="
|
||||
+ di.mDeviceCodecFormat);
|
||||
}
|
||||
if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
|
||||
btDevice.getName(), di.mDeviceCodecFormat) != AudioSystem.AUDIO_STATUS_OK) {
|
||||
// force A2DP device disconnection in case of error so that AudioService state
|
||||
// is consistent with audio policy manager state
|
||||
final int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
|
||||
setBluetoothA2dpDeviceConnectionState(
|
||||
btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
|
||||
false /* suppressNoisyIntent */, musicDevice,
|
||||
-1 /* a2dpVolume */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void onBluetoothA2dpActiveDeviceChange(
|
||||
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo) {
|
||||
final BluetoothDevice btDevice = btInfo.getBtDevice();
|
||||
int a2dpVolume = btInfo.getVolume();
|
||||
final int a2dpCodec = btInfo.getCodec();
|
||||
|
||||
if (AudioService.DEBUG_DEVICES) {
|
||||
Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice);
|
||||
}
|
||||
int a2dpVolume = btInfo.getVolume();
|
||||
final int a2dpCodec = btInfo.getCodec();
|
||||
|
||||
String address = btDevice.getAddress();
|
||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||
address = "";
|
||||
}
|
||||
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
|
||||
"onBluetoothA2dpActiveDeviceChange addr=" + address));
|
||||
"onBluetoothA2dpActiveDeviceChange addr=" + address
|
||||
+ " event=" + BtHelper.a2dpDeviceEventToString(event)));
|
||||
|
||||
synchronized (mConnectedDevices) {
|
||||
//TODO original CL is not consistent between BluetoothDevice and BluetoothA2dpDeviceInfo
|
||||
@@ -344,20 +295,28 @@ public final class AudioDeviceInventory {
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
|
||||
final DeviceInfo di = mConnectedDevices.get(key);
|
||||
if (di == null) {
|
||||
Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpActiveDeviceChange");
|
||||
return;
|
||||
}
|
||||
|
||||
// Device is connected
|
||||
if (a2dpVolume != -1) {
|
||||
final AudioService.VolumeStreamState streamState =
|
||||
mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
|
||||
// Convert index to internal representation in VolumeStreamState
|
||||
a2dpVolume = a2dpVolume * 10;
|
||||
streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
"onBluetoothA2dpActiveDeviceChange");
|
||||
mDeviceBroker.setDeviceVolume(streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
|
||||
if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
|
||||
// Device is connected
|
||||
if (a2dpVolume != -1) {
|
||||
final AudioService.VolumeStreamState streamState =
|
||||
mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
|
||||
// Convert index to internal representation in VolumeStreamState
|
||||
a2dpVolume = a2dpVolume * 10;
|
||||
streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
"onBluetoothA2dpActiveDeviceChange");
|
||||
mDeviceBroker.setDeviceVolume(
|
||||
streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
|
||||
}
|
||||
} else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
|
||||
if (di.mDeviceCodecFormat != a2dpCodec) {
|
||||
di.mDeviceCodecFormat = a2dpCodec;
|
||||
mConnectedDevices.replace(key, di);
|
||||
}
|
||||
}
|
||||
|
||||
if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
|
||||
btDevice.getName(), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
|
||||
int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
|
||||
@@ -616,52 +575,48 @@ public final class AudioDeviceInventory {
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ int handleBluetoothA2dpActiveDeviceChange(
|
||||
/*package*/ void handleBluetoothA2dpActiveDeviceChangeExt(
|
||||
@NonNull BluetoothDevice device,
|
||||
@AudioService.BtProfileConnectionState int state, int profile,
|
||||
boolean suppressNoisyIntent, int a2dpVolume) {
|
||||
// method was added by QC but never used, and now conflicts with async behavior of
|
||||
// handleBluetoothA2dpDeviceConfigChange and
|
||||
// setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
|
||||
if (false) {
|
||||
if (state == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
setBluetoothA2dpDeviceConnectionState(device, state, profile,
|
||||
suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
|
||||
if (state == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
||||
device, state, profile, suppressNoisyIntent, a2dpVolume);
|
||||
return;
|
||||
}
|
||||
// state == BluetoothProfile.STATE_CONNECTED
|
||||
synchronized (mConnectedDevices) {
|
||||
final String address = device.getAddress();
|
||||
final int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
|
||||
final String deviceKey = DeviceInfo.makeDeviceListKey(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
|
||||
DeviceInfo deviceInfo = mConnectedDevices.get(deviceKey);
|
||||
if (deviceInfo != null) {
|
||||
// Device config change for matching A2DP device
|
||||
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
|
||||
return;
|
||||
}
|
||||
// state == BluetoothProfile.STATE_CONNECTED
|
||||
synchronized (mConnectedDevices) {
|
||||
for (int i = 0; i < mConnectedDevices.size(); i++) {
|
||||
final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
|
||||
if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
|
||||
continue;
|
||||
}
|
||||
// If A2DP device exists, this is either an active device change or
|
||||
// device config change
|
||||
final String existingDevicekey = mConnectedDevices.keyAt(i);
|
||||
final String deviceName = device.getName();
|
||||
final String address = device.getAddress();
|
||||
final String newDeviceKey = DeviceInfo.makeDeviceListKey(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
|
||||
int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
|
||||
// Device not equal to existing device, active device change
|
||||
if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
|
||||
mConnectedDevices.remove(existingDevicekey);
|
||||
mConnectedDevices.put(newDeviceKey, new DeviceInfo(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
|
||||
address, a2dpCodec));
|
||||
mDeviceBroker.postA2dpActiveDeviceChange(
|
||||
new BtHelper.BluetoothA2dpDeviceInfo(
|
||||
device, a2dpVolume, a2dpCodec));
|
||||
return 0;
|
||||
} else {
|
||||
// Device config change for existing device
|
||||
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < mConnectedDevices.size(); i++) {
|
||||
deviceInfo = mConnectedDevices.valueAt(i);
|
||||
if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
|
||||
continue;
|
||||
}
|
||||
// A2DP device exists, handle active device change
|
||||
final String existingDevicekey = mConnectedDevices.keyAt(i);
|
||||
final String deviceName = device.getName();
|
||||
mConnectedDevices.remove(existingDevicekey);
|
||||
mConnectedDevices.put(deviceKey, new DeviceInfo(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
|
||||
address, a2dpCodec));
|
||||
mDeviceBroker.postA2dpActiveDeviceChange(
|
||||
new BtHelper.BluetoothA2dpDeviceInfo(
|
||||
device, a2dpVolume, a2dpCodec));
|
||||
return;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
// New A2DP device connection
|
||||
mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
|
||||
device, state, profile, suppressNoisyIntent, a2dpVolume);
|
||||
}
|
||||
|
||||
/*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
|
||||
|
||||
@@ -4094,12 +4094,9 @@ public class AudioService extends IAudioService.Stub
|
||||
* @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
|
||||
* boolean, int)
|
||||
*/
|
||||
public int handleBluetoothA2dpActiveDeviceChange(
|
||||
public void handleBluetoothA2dpActiveDeviceChange(
|
||||
BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
|
||||
int a2dpVolume) {
|
||||
// FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
|
||||
// of handleBluetoothA2dpDeviceConfigChange and
|
||||
// setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
|
||||
if (device == null) {
|
||||
throw new IllegalArgumentException("Illegal null device");
|
||||
}
|
||||
@@ -4110,7 +4107,7 @@ public class AudioService extends IAudioService.Stub
|
||||
&& state != BluetoothProfile.STATE_DISCONNECTED) {
|
||||
throw new IllegalArgumentException("Invalid state " + state);
|
||||
}
|
||||
return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
|
||||
mDeviceBroker.postBluetoothA2dpDeviceConfigChangeExt(device, state, profile,
|
||||
suppressNoisyIntent, a2dpVolume);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,19 @@ public class BtHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// A2DP device events
|
||||
/*package*/ static final int EVENT_DEVICE_CONFIG_CHANGE = 0;
|
||||
/*package*/ static final int EVENT_ACTIVE_DEVICE_CHANGE = 1;
|
||||
|
||||
/*package*/ static String a2dpDeviceEventToString(int event) {
|
||||
switch (event) {
|
||||
case EVENT_DEVICE_CONFIG_CHANGE: return "DEVICE_CONFIG_CHANGE";
|
||||
case EVENT_ACTIVE_DEVICE_CHANGE: return "ACTIVE_DEVICE_CHANGE";
|
||||
default:
|
||||
return new String("invalid event:" + event);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Interface for AudioDeviceBroker
|
||||
|
||||
|
||||
Reference in New Issue
Block a user