BluetoothA2dp的connect用于连接蓝牙耳机,代码如下:
//packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothA2dp.java
public final class BluetoothA2dp implements BluetoothProfile {
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothA2dp service = getService();
final boolean defaultValue = false;
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
} else if (isEnabled() && isValidDevice(device)) {
try {
final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
service.connectWithAttribution(device, mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
} catch (RemoteException | TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}
return defaultValue;
}
}
A2dpService connectWithAttribution
调用IBluetoothA2dp的connectWithAttribution方法,IBluetoothA2dp是一个接口,由A2dpService的内部类BluetoothA2dpBinder 实现:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpService.java
public class A2dpService extends ProfileService {
static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub
implements IProfileServiceBinder {
public void connectWithAttribution(BluetoothDevice device, AttributionSource source,
SynchronousResultReceiver receiver) {
try {
A2dpService service = getService(source);
boolean result = false;
if (service != null) {
result = service.connect(device);
}
receiver.send(result);
} catch (RuntimeException e) {
receiver.propagateException(e);
}
}
}
}
调用A2dpService的connect方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpService.java
public class A2dpService extends ProfileService {
public boolean connect(BluetoothDevice device) {
if (DBG) {
Log.d(TAG, "connect(): " + device);
}
if (getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
Log.e(TAG, "Cannot connect to " + device + " : CONNECTION_POLICY_FORBIDDEN");
return false;
}
if (!Utils.arrayContains(mAdapterService.getRemoteUuids(device),
BluetoothUuid.A2DP_SINK)) {
Log.e(TAG, "Cannot connect to " + device + " : Remote does not have A2DP Sink UUID");
return false;
}
synchronized (mStateMachines) {
if (!connectionAllowedCheckMaxDevices(device)) {
// when mMaxConnectedAudioDevices is one, disconnect current device first.
if (mMaxConnectedAudioDevices == 1) {
List<BluetoothDevice> sinks = getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING,
BluetoothProfile.STATE_DISCONNECTING});
for (BluetoothDevice sink : sinks) {
if (sink.equals(device)) {
Log.w(TAG, "Connecting to device " + device + " : disconnect skipped");
continue;
}
disconnect(sink);
}
} else {
Log.e(TAG, "Cannot connect to " + device + " : too many connected devices");
return false;
}
}
A2dpStateMachine smConnect = getOrCreateStateMachine(device); //取得或创建状态机
if (smConnect == null) {
Log.e(TAG, "Cannot connect to " + device + " : no state machine");
return false;
}
smConnect.sendMessage(A2dpStateMachine.CONNECT); //向状态机发送CONNECT命令
return true;
}
}
}
向状态机发送CONNECT命令,在A2dpStateMachine的状态类Disconnected的processMessage方法中处理:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
final class A2dpStateMachine extends StateMachine {
class Disconnected extends State {
public boolean processMessage(Message message) {
switch (message.what) {
case CONNECT:
if (DBG) Log.d(TAG, "Connect");
transitionTo(mConnecting); //迁移到Connecting状态
return true;
}
return false;
}
}
}
迁移到Connecting状态,会调用Connecting状态类的enter方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
final class A2dpStateMachine extends StateMachine {
protected final A2dpSinkNativeInterface mNativeInterface;
class Connecting extends State {
public void enter() {
if (DBG) Log.d(TAG, "Enter Connecting");
onConnectionStateChanged(BluetoothProfile.STATE_CONNECTING); 调用onConnectionStateChanged方法,发送A2DP连接中广播
sendMessageDelayed(CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS); //启动超时定时器
if (!mIncomingConnection) {
mNativeInterface.connectA2dpSink(mDevice); //调用A2dpSinkNativeInterface的connectA2dpSink方法
}
super.enter();
}
}
}
A2dpSinkNativeInterface connectA2dpSink
调用A2dpSinkNativeInterface的connectA2dpSink方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java
public class A2dpSinkNativeInterface {
public boolean connectA2dpSink(BluetoothDevice device) {
return connectA2dpNative(getByteAddress(device));
}
}
调用connectA2dpNative方法,connectA2dpNative是一个Native方法,实现代码如下:
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_a2dp.cpp
static const btav_source_interface_t* sBluetoothA2dpInterface = nullptr;
static jboolean connectA2dpNative(JNIEnv* env, jobject object,
jbyteArray address) {
ALOGI("%s: sBluetoothA2dpInterface: %p", __func__, sBluetoothA2dpInterface);
std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
if (!sBluetoothA2dpInterface) {
ALOGE("%s: Failed to get the Bluetooth A2DP Interface", __func__);
return JNI_FALSE;
}
jbyte* addr = env->GetByteArrayElements(address, nullptr);
if (!addr) {
jniThrowIOException(env, EINVAL);
return JNI_FALSE;
}
RawAddress bd_addr;
bd_addr.FromOctets(reinterpret_cast<const uint8_t*>(addr));
bt_status_t status = sBluetoothA2dpInterface->connect(bd_addr);
if (status != BT_STATUS_SUCCESS) {
ALOGE("%s: Failed A2DP connection, status: %d", __func__, status);
}
env->ReleaseByteArrayElements(address, addr, 0);
return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
调用btav_source_interface_t的connect方法,btav_source_interface_t是一个结构体,在bt_av.h中定义,a2dp_source.cc中实现:
//packages/modules/Bluetooth/system/service/a2dp_source.cc
bool A2dpSource::Connect(const std::string& device_address) {
RawAddress addr = PARSE_ADDR(device_address);
LockGuard lock(mutex_);
TRY_RET_FUNC(
hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->connect(
addr) == BT_STATUS_SUCCESS);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。
A2dpNativeInterface onConnectionStateChanged
当蓝牙协议栈(BT Stack)处理完相关请求后,会调用A2dpNativeInterface的onConnectionStateChanged方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpSinkNativeInterface.java
public class A2dpNativeInterface {
private void onConnectionStateChanged(byte[] address, int state) {
A2dpStackEvent event =
new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
event.device = getDevice(address);
event.valueInt = state;
if (DBG) {
Log.d(TAG, "onConnectionStateChanged: " + event);
}
sendMessageToService(event);
}
}
发送EVENT_TYPE_CONNECTION_STATE_CHANGED消息,发送的消息在A2dpService 的messageFromNative方法中处理:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpService.java
public class A2dpService extends ProfileService {
void messageFromNative(A2dpStackEvent stackEvent) {
Objects.requireNonNull(stackEvent.device,
"Device should never be null, event: " + stackEvent);
synchronized (mStateMachines) {
BluetoothDevice device = stackEvent.device;
A2dpStateMachine sm = mStateMachines.get(device);
if (sm == null) {
if (stackEvent.type == A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
switch (stackEvent.valueInt) {
case A2dpStackEvent.CONNECTION_STATE_CONNECTED:
case A2dpStackEvent.CONNECTION_STATE_CONNECTING:
// Create a new state machine only when connecting to a device
if (!connectionAllowedCheckMaxDevices(device)) {
Log.e(TAG, "Cannot connect to " + device
+ " : too many connected devices");
return;
}
sm = getOrCreateStateMachine(device);
break;
default:
break;
}
}
}
if (sm == null) {
Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent);
return;
}
sm.sendMessage(A2dpStateMachine.STACK_EVENT, stackEvent);
}
}
}
发送STACK_EVENT消息,发送的消息在A2dpStateMachine 的内部状态类Connecting的processMessage中处理:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpStateMachine .java
final class A2dpStateMachine extends StateMachine {
class Connecting extends State {
public boolean processMessage(Message message) {
log("Connecting process message(" + mDevice + "): "
+ messageWhatToString(message.what));
switch (message.what) {
case STACK_EVENT:
A2dpStackEvent event = (A2dpStackEvent) message.obj;
log("Connecting: stack event: " + event);
if (!mDevice.equals(event.device)) {
Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event);
}
switch (event.type) {
case A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
processConnectionEvent(event.valueInt);
break;
default:
Log.e(TAG, "Connecting: ignoring stack event: " + event);
break;
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
}
调用processConnectionEvent方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpStateMachine .java
final class A2dpStateMachine extends StateMachine {
class Connecting extends State {
private void processConnectionEvent(int event) {
switch (event) {
case A2dpStackEvent.CONNECTION_STATE_DISCONNECTED:
Log.w(TAG, "Connecting device disconnected: " + mDevice);
transitionTo(mDisconnected);
break;
case A2dpStackEvent.CONNECTION_STATE_CONNECTED:
transitionTo(mConnected); //迁移到Connected状态
break;
case A2dpStackEvent.CONNECTION_STATE_CONNECTING:
// Ignored - probably an event that the outgoing connection was initiated
break;
case A2dpStackEvent.CONNECTION_STATE_DISCONNECTING:
Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice);
transitionTo(mDisconnecting);
break;
default:
Log.e(TAG, "Incorrect event: " + event);
break;
}
}
}
}
迁移到Connected状态,会调用Connected 的enter方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpStateMachine .java
final class A2dpStateMachine extends StateMachine {
class Connected extends State {
public void enter() {
Message currentMessage = getCurrentMessage();
Log.i(TAG, "Enter Connected(" + mDevice + "): " + (currentMessage == null ? "null"
: messageWhatToString(currentMessage.what)));
mConnectionState = BluetoothProfile.STATE_CONNECTED;
removeDeferredMessages(CONNECT);
//每次设备连接时,我们都要重新检查它是否支持可选的编解码器(也许它有固件更新等),如果它与我们之前保存的状态不同,请保存该状态。
// Each time a device connects, we want to re-check if it supports optional
// codecs (perhaps it's had a firmware update, etc.) and save that state if
// it differs from what we had saved before.
mA2dpService.updateOptionalCodecsSupport(mDevice); //更新并启动可选的编解码器状态更改为本机。
broadcastConnectionState(mConnectionState, mLastConnectionState); //发送Connection状态变更广播
// Upon connected, the audio starts out as stopped
broadcastAudioState(BluetoothA2dp.STATE_NOT_PLAYING,
BluetoothA2dp.STATE_PLAYING); //发送Audio状态变化广播
}
}
}
A2dpService updateOptionalCodecsSupport
调用A2dpService的updateOptionalCodecsSupport方法:
//packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpService.java
public class A2dpService extends ProfileService {
public void updateOptionalCodecsSupport(BluetoothDevice device) {
int previousSupport = getSupportsOptionalCodecs(device);
boolean supportsOptional = false;
boolean hasMandatoryCodec = false;
synchronized (mStateMachines) {
A2dpStateMachine sm = mStateMachines.get(device);
if (sm == null) {
return;
}
BluetoothCodecStatus codecStatus = sm.getCodecStatus(); //获取BluetoothCodecStatus 状态
if (codecStatus != null) {
for (BluetoothCodecConfig config : codecStatus.getCodecsSelectableCapabilities()) {
if (config.isMandatoryCodec()) {
hasMandatoryCodec = true;
} else {
supportsOptional = true;
}
}
}
}
if (!hasMandatoryCodec) {
// Mandatory codec(SBC) is not selectable. It could be caused by the remote device
// select codec before native finish get codec capabilities. Stop use this codec
// status as the reference to support/enable optional codecs.
Log.i(TAG, "updateOptionalCodecsSupport: Mandatory codec is not selectable.");
return;
}
if (previousSupport == BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN
|| supportsOptional != (previousSupport
== BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED)) {
setSupportsOptionalCodecs(device, supportsOptional);
}
if (supportsOptional) {
int enabled = getOptionalCodecsEnabled(device);
switch (enabled) {
case BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN:
// Enable optional codec by default.
setOptionalCodecsEnabled(device, BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
// Fall through intended
case BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED:
enableOptionalCodecs(device);
break;
case BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED:
disableOptionalCodecs(device);
break;
}
}
}
}
这部分为可选解码器相关,我们可以先不关注,到这里BluetoothA2dp的disconnet流程就分析完了。