Android 9 原生设置关于蓝牙设置(五)

蓝牙配对及A2DP连接

参考:蓝牙配置流程

  当点击设置界面的某个蓝牙设备时会调用DeviceListPreferenceFragment里面:
在这里插入图片描述
  最终调用BluetoothDevicePreference.onClicked(),主要代码如下:
在这里插入图片描述
  上面的逻辑里会根据不同的情况执行不同的逻辑,一目了然。

蓝牙配对

  调用CachedBluetoothDevice.startPairing()
在这里插入图片描述
  配对之前,如果当前处于蓝牙扫描状态,则停止蓝牙扫描。然后调用createBond()开始绑定(即配对)了。
  BluetoothDevice.createBond()>adapterservice.createBond()>adapterservice.createBond()>向状态机发送绑定消息》  BondStateMachine.createBond()>AdapterService.createBondNative()>JNI==>hw,
在这里插入图片描述

蓝牙连接

  当配对成功之后,会发送BONDING_STATE_CHANGE消息到BondStateMachine:
  BondStateMachine::PendingCommandState.processMessage()
在这里插入图片描述
  调用BondStateMachine::PendingCommandState.sendIntent()发ACTION_BOND_STATE_CHANGED消息给应用软件:
在这里插入图片描述
  上面先调用了AdapterProperties.onBondStateChanged(),其中调用setBondState更新远程设备的Bond状态。
  ACTION_BOND_STATE_CHANGED消息给Setting软件的BluetoothEventManager处理,比如接收到bond完成事件BondStateChangedHandler,里面调用了

            cachedDevice.onBondingStateChanged(bondState);

在这里插入图片描述
  这里省略一些逻辑,之后调用到connectAutoConnectableProfiles()
在这里插入图片描述
  for循环遍历了所以支持的蓝牙协议,如果该协议允许自动连接,则尝试connect。
在这里插入图片描述
  连接成功会有以下打印:
在这里插入图片描述
这里了解一下A2dpProfile.connect()
在这里插入图片描述
  先断开已经连接的A2DP远程设备,再连接指定的设备。
A2dpProfile.connect()–>BluetoothA2dp.connect()–>A2dpService.connect() 发送A2dpStateMachine.CONNECT给状态机–>A2dpStateMachine.Disconnected.processMessage() -->connectA2dpNative(),连接超时时间是30秒。
在这里插入图片描述
在这里插入图片描述
  上面代码
  (1)处是发送一个连接蓝牙状态改变事件。
  (2)进行a2dp连接,很明显就要进入jni里了
  (3)把要连接的远程蓝牙设备设置为目标设备mTargetDevice,状态转换到==》pending==>connected
这里只讲连接,所以下面要分析jni了。com_android_bluetooth_a2dp.cpp

static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
    
    
    jbyte *addr;
    bt_bdaddr_t * btAddr;
    bt_status_t status;
 
    ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface);
    if (!sBluetoothA2dpInterface) return JNI_FALSE;
 
    addr = env->GetByteArrayElements(address, NULL);
    btAddr = (bt_bdaddr_t *) addr;
    if (!addr) {
    
    
        jniThrowIOException(env, EINVAL);
        return JNI_FALSE;
    }
 
    if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
    
    
        ALOGE("Failed HF connection, status: %d", status);
    }
    env->ReleaseByteArrayElements(address, addr, 0);
return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

  那么这个sBluetoothA2dpInterface这个是什么呢?其实这个就相当于java中对外提供的api接口,只是在c中是头文件而已。既然是蓝牙肯定是在蓝牙的头文件里bt_av.h里

typedef struct {
    
    
 
    /** set to sizeof(btav_interface_t) */
    size_t          size;
    /**
     * Register the BtAv callbacks
     */
    bt_status_t (*init)( btav_callbacks_t* callbacks );
 
    /** connect to headset */
    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
    /** dis-connect from headset */
    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
 
    /** Closes the interface. */
    void  (*cleanup)( void );
} btav_interface_t;

  接下来就调用到./btif/src/btif_av.c,此处省略。
  

  蓝牙A2DP连接成功,bluedroid回调com_android_bluetooth_a2dp.cpp bta2dp_connection_state_callback(),然后回调A2dpStateMachine.onConnectionStateChanged()
在这里插入图片描述
  发送STACK_EVENT消息,因当前状态是Pending,所以调用Pending.processMessage():
在这里插入图片描述
processConnectionEvent()
在这里插入图片描述
在这里插入图片描述
发送MSG_CONNECTION_STATE_CHANGED消息,留意下参数内容。
在这里插入图片描述
  发送BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED广播,并把状态信息传递过去。另外会调用notifyProfileConnectionStateChanged(),修改Profile的优先级等(因为蓝牙带宽是有限的)。
  在LocalBluetoothProfileManager.updateLocalProfiles()有注册接收BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED广播,由StateChangedHandler类处理广播:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  cachedDevice.refresh()–>dispatchAttributesChanged()–>BluetoothDevicePreference.onDeviceAttributesChanged(),更新了UI界面关于蓝牙远程设备对应的Prcference。

猜你喜欢

转载自blog.csdn.net/suwen8100/article/details/126705716