Merge "AudioService: fix A2DP (dis)connection during media playback" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-04-25 01:02:57 +00:00
committed by Android (Google) Code Review
4 changed files with 151 additions and 64 deletions

View File

@@ -199,18 +199,61 @@ public class AudioSystem
/** @hide */ /** @hide */
public static final int AUDIO_FORMAT_LDAC = 0x23000000; public static final int AUDIO_FORMAT_LDAC = 0x23000000;
/** @hide */
@IntDef(flag = false, prefix = "AUDIO_FORMAT_", value = {
AUDIO_FORMAT_INVALID,
AUDIO_FORMAT_DEFAULT,
AUDIO_FORMAT_AAC,
AUDIO_FORMAT_SBC,
AUDIO_FORMAT_APTX,
AUDIO_FORMAT_APTX_HD,
AUDIO_FORMAT_LDAC }
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioFormatNativeEnumForBtCodec {}
/** /**
* @hide * @hide
* Convert audio format enum values to Bluetooth codec values * Convert audio format enum values to Bluetooth codec values
*/ */
public static int audioFormatToBluetoothSourceCodec(int audioFormat) { public static int audioFormatToBluetoothSourceCodec(
@AudioFormatNativeEnumForBtCodec int audioFormat) {
switch (audioFormat) { switch (audioFormat) {
case AUDIO_FORMAT_AAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC; case AUDIO_FORMAT_AAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC;
case AUDIO_FORMAT_SBC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC; case AUDIO_FORMAT_SBC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC;
case AUDIO_FORMAT_APTX: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX; case AUDIO_FORMAT_APTX: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
case AUDIO_FORMAT_APTX_HD: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD; case AUDIO_FORMAT_APTX_HD: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
case AUDIO_FORMAT_LDAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC; case AUDIO_FORMAT_LDAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
default: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID; default:
Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat)
+ " for conversion to BT codec");
return BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
}
}
/**
* @hide
* Convert a Bluetooth codec to an audio format enum
* @param btCodec the codec to convert.
* @return the audio format, or {@link #AUDIO_FORMAT_DEFAULT} if unknown
*/
public static @AudioFormatNativeEnumForBtCodec int bluetoothCodecToAudioFormat(int btCodec) {
switch (btCodec) {
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC:
return AudioSystem.AUDIO_FORMAT_SBC;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC:
return AudioSystem.AUDIO_FORMAT_AAC;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX:
return AudioSystem.AUDIO_FORMAT_APTX;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD:
return AudioSystem.AUDIO_FORMAT_APTX_HD;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
return AudioSystem.AUDIO_FORMAT_LDAC;
default:
Log.e(TAG, "Unknown BT codec 0x" + Integer.toHexString(btCodec)
+ " for conversion to audio format");
// TODO returning DEFAULT is the current behavior, should this return INVALID?
return AudioSystem.AUDIO_FORMAT_DEFAULT;
} }
} }

View File

@@ -255,7 +255,21 @@ import java.io.PrintWriter;
// redefine equality op so we can match messages intended for this device // redefine equality op so we can match messages intended for this device
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
return mDevice.equals(o); if (o == null) {
return false;
}
if (this == o) {
return true;
}
if (o instanceof BtDeviceConnectionInfo) {
return mDevice.equals(((BtDeviceConnectionInfo) o).mDevice);
}
return false;
}
@Override
public String toString() {
return "BtDeviceConnectionInfo dev=" + mDevice.toString();
} }
} }
@@ -266,27 +280,45 @@ import java.io.PrintWriter;
final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
suppressNoisyIntent, a2dpVolume); suppressNoisyIntent, a2dpVolume);
// when receiving a request to change the connection state of a device, this last request // operations of removing and posting messages related to A2DP device state change must be
// is the source of truth, so cancel all previous requests // mutually exclusive
removeAllA2dpConnectionEvents(device); synchronized (mDeviceStateLock) {
// when receiving a request to change the connection state of a device, this last
// request is the source of truth, so cancel all previous requests that are already in
// the handler
removeScheduledA2dpEvents(device);
sendLMsgNoDelay( sendLMsgNoDelay(
state == BluetoothProfile.STATE_CONNECTED state == BluetoothProfile.STATE_CONNECTED
? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION ? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION
: MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION, : MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
SENDMSG_QUEUE, info); SENDMSG_QUEUE, info);
}
} }
/** remove all previously scheduled connection and disconnection events for the given device */ /** remove all previously scheduled connection and state change events for the given device */
private void removeAllA2dpConnectionEvents(@NonNull BluetoothDevice device) { @GuardedBy("mDeviceStateLock")
mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION, private void removeScheduledA2dpEvents(@NonNull BluetoothDevice device) {
device); mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, device);
mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
device); final BtDeviceConnectionInfo connectionInfoToRemove = new BtDeviceConnectionInfo(device,
mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, // the next parameters of the constructor will be ignored when finding the message
device); // to remove as the equality of the message's object is tested on the device itself
mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, // (see BtDeviceConnectionInfo.equals() method override)
device); BluetoothProfile.STATE_CONNECTED, 0, false, -1);
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
connectionInfoToRemove);
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
connectionInfoToRemove);
final BtHelper.BluetoothA2dpDeviceInfo devInfoToRemove =
new BtHelper.BluetoothA2dpDeviceInfo(device);
mBrokerHandler.removeEqualMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
devInfoToRemove);
mBrokerHandler.removeEqualMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
devInfoToRemove);
mBrokerHandler.removeEqualMessages(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE,
devInfoToRemove);
} }
private static final class HearingAidDeviceConnectionInfo { private static final class HearingAidDeviceConnectionInfo {
@@ -493,6 +525,7 @@ import java.io.PrintWriter;
sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
} }
@GuardedBy("mDeviceStateLock")
/*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state, /*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state,
@NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
sendILMsg(state == BluetoothA2dp.STATE_CONNECTED sendILMsg(state == BluetoothA2dp.STATE_CONNECTED
@@ -624,10 +657,12 @@ import java.io.PrintWriter;
// must be called synchronized on mConnectedDevices // must be called synchronized on mConnectedDevices
/*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) { /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
return (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, final BtHelper.BluetoothA2dpDeviceInfo devInfoToCheck =
new BtHelper.BluetoothA2dpDeviceInfo(btDevice)) new BtHelper.BluetoothA2dpDeviceInfo(btDevice);
|| mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, return (mBrokerHandler.hasEqualMessages(
new BtHelper.BluetoothA2dpDeviceInfo(btDevice))); MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, devInfoToCheck)
|| mBrokerHandler.hasEqualMessages(
MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, devInfoToCheck));
} }
/*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) { /*package*/ void setA2dpTimeout(String address, int a2dpCodec, int delayMs) {
@@ -808,6 +843,9 @@ import java.io.PrintWriter;
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
synchronized (mDeviceStateLock) { synchronized (mDeviceStateLock) {
a2dpCodec = mBtHelper.getA2dpCodec(btDevice); a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
// TODO: name of method being called on AudioDeviceInventory is currently
// misleading (config change vs active device change), to be
// reconciliated once the BT side has been updated.
mDeviceInventory.onBluetoothA2dpActiveDeviceChange( mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
BtHelper.EVENT_DEVICE_CONFIG_CHANGE); BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
@@ -900,7 +938,7 @@ import java.io.PrintWriter;
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: { case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: {
final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj; final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent " "msg: setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
+ " state=" + info.mState + " state=" + info.mState
// only querying address as this is the only readily available // only querying address as this is the only readily available
// field on the device // field on the device
@@ -917,7 +955,7 @@ import java.io.PrintWriter;
final HearingAidDeviceConnectionInfo info = final HearingAidDeviceConnectionInfo info =
(HearingAidDeviceConnectionInfo) msg.obj; (HearingAidDeviceConnectionInfo) msg.obj;
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"setHearingAidDeviceConnectionState state=" + info.mState "msg: setHearingAidDeviceConnectionState state=" + info.mState
+ " addr=" + info.mDevice.getAddress() + " addr=" + info.mDevice.getAddress()
+ " supprNoisy=" + info.mSupprNoisy + " supprNoisy=" + info.mSupprNoisy
+ " src=" + info.mEventSource)).printLog(TAG)); + " src=" + info.mEventSource)).printLog(TAG));
@@ -962,13 +1000,19 @@ import java.io.PrintWriter;
private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8; private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8;
private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
private static final int MSG_IL_BTA2DP_TIMEOUT = 10; private static final int MSG_IL_BTA2DP_TIMEOUT = 10;
// process change of A2DP device configuration, obj is BluetoothDevice
private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11;
private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12;
private static final int MSG_REPORT_NEW_ROUTES = 13; private static final int MSG_REPORT_NEW_ROUTES = 13;
private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
private static final int MSG_I_DISCONNECT_BT_SCO = 16; private static final int MSG_I_DISCONNECT_BT_SCO = 16;
// process active A2DP device change, obj is BtHelper.BluetoothA2dpDeviceInfo
private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18; private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
private static final int MSG_DISCONNECT_A2DP = 19; private static final int MSG_DISCONNECT_A2DP = 19;
private static final int MSG_DISCONNECT_A2DP_SINK = 20; private static final int MSG_DISCONNECT_A2DP_SINK = 20;
private static final int MSG_DISCONNECT_BT_HEARING_AID = 21; private static final int MSG_DISCONNECT_BT_HEARING_AID = 21;
@@ -977,13 +1021,18 @@ import java.io.PrintWriter;
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24; private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25; private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26; private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
// process change of state, obj is BtHelper.BluetoothA2dpDeviceInfo
private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED = 27; private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED = 27;
private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED = 28; private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED = 28;
// process external command to (dis)connect an A2DP device
// process external command to (dis)connect an A2DP device, obj is BtDeviceConnectionInfo
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION = 29; private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION = 29;
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION = 30; private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION = 30;
// process external command to (dis)connect a hearing aid device // process external command to (dis)connect a hearing aid device
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31; private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
// a ScoClient died in BtHelper // a ScoClient died in BtHelper
private static final int MSG_L_SCOCLIENT_DIED = 32; private static final int MSG_L_SCOCLIENT_DIED = 32;
private static final int MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY = 33; private static final int MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY = 33;

View File

@@ -289,11 +289,11 @@ public class AudioDeviceInventory {
address = ""; address = "";
} }
final int a2dpCodec = btInfo.getCodec(); final @AudioSystem.AudioFormatNativeEnumForBtCodec int a2dpCodec = btInfo.getCodec();
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"A2DP sink connected: device addr=" + address + " state=" + state "A2DP sink connected: device addr=" + address + " state=" + state
+ " codec=" + a2dpCodec + " codec=" + AudioSystem.audioFormatToString(a2dpCodec)
+ " vol=" + a2dpVolume)); + " vol=" + a2dpVolume));
new MediaMetrics.Item(mMetricsId + "a2dp") new MediaMetrics.Item(mMetricsId + "a2dp")
@@ -422,7 +422,7 @@ public class AudioDeviceInventory {
Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice); Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice);
} }
int a2dpVolume = btInfo.getVolume(); int a2dpVolume = btInfo.getVolume();
final int a2dpCodec = btInfo.getCodec(); @AudioSystem.AudioFormatNativeEnumForBtCodec final int a2dpCodec = btInfo.getCodec();
String address = btDevice.getAddress(); String address = btDevice.getAddress();
if (!BluetoothAdapter.checkBluetoothAddress(address)) { if (!BluetoothAdapter.checkBluetoothAddress(address)) {
@@ -435,7 +435,8 @@ public class AudioDeviceInventory {
synchronized (mDevicesLock) { synchronized (mDevicesLock) {
if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) { if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"A2dp config change ignored (scheduled connection change)")); "A2dp config change ignored (scheduled connection change)")
.printLog(TAG));
mmi.set(MediaMetrics.Property.EARLY_RETURN, "A2dp config change ignored") mmi.set(MediaMetrics.Property.EARLY_RETURN, "A2dp config change ignored")
.record(); .record();
return; return;
@@ -476,8 +477,9 @@ public class AudioDeviceInventory {
if (res != AudioSystem.AUDIO_STATUS_OK) { if (res != AudioSystem.AUDIO_STATUS_OK) {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"APM handleDeviceConfigChange failed for A2DP device addr=" "APM handleDeviceConfigChange failed for A2DP device addr=" + address
+ address + " codec=" + a2dpCodec).printLog(TAG)); + " codec=" + AudioSystem.audioFormatToString(a2dpCodec))
.printLog(TAG));
int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC); int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
// force A2DP device disconnection in case of error so that AudioService state is // force A2DP device disconnection in case of error so that AudioService state is
@@ -488,8 +490,9 @@ public class AudioDeviceInventory {
-1 /* a2dpVolume */); -1 /* a2dpVolume */);
} else { } else {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"APM handleDeviceConfigChange success for A2DP device addr=" "APM handleDeviceConfigChange success for A2DP device addr=" + address
+ address + " codec=" + a2dpCodec).printLog(TAG)); + " codec=" + AudioSystem.audioFormatToString(a2dpCodec))
.printLog(TAG));
} }
} }
mmi.record(); mmi.record();
@@ -816,20 +819,17 @@ public class AudioDeviceInventory {
if (AudioService.DEBUG_DEVICES) { if (AudioService.DEBUG_DEVICES) {
Log.i(TAG, "setBluetoothA2dpDeviceConnectionState device: " + device Log.i(TAG, "setBluetoothA2dpDeviceConnectionState device: " + device
+ " state: " + state + " delay(ms): " + delay + "codec:" + a2dpCodec + " state: " + state + " delay(ms): " + delay
+ " codec:" + Integer.toHexString(a2dpCodec)
+ " suppressNoisyIntent: " + suppressNoisyIntent); + " suppressNoisyIntent: " + suppressNoisyIntent);
} }
final BtHelper.BluetoothA2dpDeviceInfo a2dpDeviceInfo = final BtHelper.BluetoothA2dpDeviceInfo a2dpDeviceInfo =
new BtHelper.BluetoothA2dpDeviceInfo(device, a2dpVolume, a2dpCodec); new BtHelper.BluetoothA2dpDeviceInfo(device, a2dpVolume, a2dpCodec);
if (profile == BluetoothProfile.A2DP) { if (profile == BluetoothProfile.A2DP) {
if (delay == 0) { mDeviceBroker.postA2dpSinkConnection(state,
onSetA2dpSinkConnectionState(a2dpDeviceInfo, state);
} else {
mDeviceBroker.postA2dpSinkConnection(state,
a2dpDeviceInfo, a2dpDeviceInfo,
delay); delay);
}
} else { //profile == BluetoothProfile.A2DP_SINK } else { //profile == BluetoothProfile.A2DP_SINK
mDeviceBroker.postA2dpSourceConnection(state, mDeviceBroker.postA2dpSourceConnection(state,
a2dpDeviceInfo, a2dpDeviceInfo,

View File

@@ -135,7 +135,7 @@ public class BtHelper {
/*package*/ static class BluetoothA2dpDeviceInfo { /*package*/ static class BluetoothA2dpDeviceInfo {
private final @NonNull BluetoothDevice mBtDevice; private final @NonNull BluetoothDevice mBtDevice;
private final int mVolume; private final int mVolume;
private final int mCodec; private final @AudioSystem.AudioFormatNativeEnumForBtCodec int mCodec;
BluetoothA2dpDeviceInfo(@NonNull BluetoothDevice btDevice) { BluetoothA2dpDeviceInfo(@NonNull BluetoothDevice btDevice) {
this(btDevice, -1, AudioSystem.AUDIO_FORMAT_DEFAULT); this(btDevice, -1, AudioSystem.AUDIO_FORMAT_DEFAULT);
@@ -155,15 +155,26 @@ public class BtHelper {
return mVolume; return mVolume;
} }
public int getCodec() { public @AudioSystem.AudioFormatNativeEnumForBtCodec int getCodec() {
return mCodec; return mCodec;
} }
// redefine equality op so we can match messages intended for this device // redefine equality op so we can match messages intended for this device
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
return mBtDevice.equals(o); if (o == null) {
return false;
}
if (this == o) {
return true;
}
if (o instanceof BluetoothA2dpDeviceInfo) {
return mBtDevice.equals(((BluetoothA2dpDeviceInfo) o).getBtDevice());
}
return false;
} }
} }
// A2DP device events // A2DP device events
@@ -249,7 +260,8 @@ public class BtHelper {
mA2dp.setAvrcpAbsoluteVolume(index); mA2dp.setAvrcpAbsoluteVolume(index);
} }
/*package*/ synchronized int getA2dpCodec(@NonNull BluetoothDevice device) { /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getA2dpCodec(
@NonNull BluetoothDevice device) {
if (mA2dp == null) { if (mA2dp == null) {
return AudioSystem.AUDIO_FORMAT_DEFAULT; return AudioSystem.AUDIO_FORMAT_DEFAULT;
} }
@@ -261,7 +273,7 @@ public class BtHelper {
if (btCodecConfig == null) { if (btCodecConfig == null) {
return AudioSystem.AUDIO_FORMAT_DEFAULT; return AudioSystem.AUDIO_FORMAT_DEFAULT;
} }
return mapBluetoothCodecToAudioFormat(btCodecConfig.getCodecType()); return AudioSystem.bluetoothCodecToAudioFormat(btCodecConfig.getCodecType());
} }
// @GuardedBy("AudioDeviceBroker.mSetModeLock") // @GuardedBy("AudioDeviceBroker.mSetModeLock")
@@ -967,23 +979,6 @@ public class BtHelper {
return result; return result;
} }
private int mapBluetoothCodecToAudioFormat(int btCodecType) {
switch (btCodecType) {
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC:
return AudioSystem.AUDIO_FORMAT_SBC;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC:
return AudioSystem.AUDIO_FORMAT_AAC;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX:
return AudioSystem.AUDIO_FORMAT_APTX;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD:
return AudioSystem.AUDIO_FORMAT_APTX_HD;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
return AudioSystem.AUDIO_FORMAT_LDAC;
default:
return AudioSystem.AUDIO_FORMAT_DEFAULT;
}
}
/** /**
* Returns the String equivalent of the btCodecType. * Returns the String equivalent of the btCodecType.
* *