HF 笔记

 2023-09-05 阅读 90 评论 0

摘要:Attribute: Bluetooth Profile Descriptor List SDP_AddProfileDescriptorList  创建一个属性 本地HF角色的属性 SDP_AddAttribute添加属性 connect_audio /********************************************************************************* Function connect_audio** De

Attribute: Bluetooth Profile Descriptor List
SDP_AddProfileDescriptorList 
在这里插入图片描述
创建一个属性在这里插入图片描述
本地HF角色的属性
在这里插入图片描述
在这里插入图片描述
SDP_AddAttribute添加属性

connect_audio

/********************************************************************************* Function         connect_audio** Description     create an audio connection** Returns         bt_status_t*******************************************************************************/
static bt_status_t connect_audio(const RawAddress* bd_addr) {btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);if ((BTIF_HF_CLIENT_FEATURES & BTA_HF_CLIENT_FEAT_CODEC) &&(cb->peer_feat & BTA_HF_CLIENT_PEER_CODEC)) {BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BCC, 0, 0, NULL);} else {BTA_HfClientAudioOpen(cb->handle);}
BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BCC, 0, 0, NULL);

bta_hf_client_send_at_bcc

bta_hf_client_send_at(client_cb, BTA_HF_CLIENT_AT_BCC, buf, strlen(buf));

PORT_WriteData

port_write

RFCOMM_DataReq

rfc_port_sm_execute

case RFC_STATE_OPENED:rfc_port_sm_opened(p_port, event, p_data);
case RFC_EVENT_DATA:/* Send credits in the frame.  Pass them in the layer specific member of* the hdr. *//* There might be an initial case when we reduced rx_max and credit_rx is* still *//* bigger.  Make sure that we do not send 255 */if ((p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) &&(((BT_HDR*)p_data)->len < p_port->peer_mtu) &&(!p_port->rx.user_fc) &&(p_port->credit_rx_max > p_port->credit_rx)) {((BT_HDR*)p_data)->layer_specific =(uint8_t)(p_port->credit_rx_max - p_port->credit_rx);p_port->credit_rx = p_port->credit_rx_max;} else {((BT_HDR*)p_data)->layer_specific = 0;}rfc_send_buf_uih(p_port->rfc.p_mcb, p_port->dlci, (BT_HDR*)p_data);
    L2CA_DataWrite(p_mcb->lcid, p_buf);

事件:

/********************************************************************************* Function         bta_hf_client_rfc_do_open** Description      Open an RFCOMM connection to the peer device.*** Returns          void*******************************************************************************/
void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA* p_data) {tBTA_HF_CLIENT_CB* client_cb =bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);if (client_cb == NULL) {APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,p_data->hdr.layer_specific);return;}BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_HF_HANDSFREE,client_cb->cli_sec_mask, BT_PSM_RFCOMM,BTM_SEC_PROTO_RFCOMM, client_cb->peer_scn);if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, client_cb->peer_scn,false, BTA_HF_CLIENT_MTU, client_cb->peer_addr,&(client_cb->conn_handle),bta_hf_client_mgmt_cback) == PORT_SUCCESS) {bta_hf_client_setup_port(client_cb->conn_handle);APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d",client_cb->conn_handle);}/* RFCOMM create connection failed; send ourselves RFCOMM close event */else {bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data);}
}
/********************************************************************************* Function         bta_hf_client_setup_port** Description      Setup RFCOMM port for use by HF Client.*** Returns          void*******************************************************************************/
void bta_hf_client_setup_port(uint16_t handle) {PORT_SetEventMask(handle, PORT_EV_RXCHAR);PORT_SetEventCallback(handle, bta_hf_client_port_cback);
}
/********************************************************************************* Function         bta_hf_client_rfc_data** Description      Read and process data from RFCOMM.*** Returns          void*******************************************************************************/
void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA* p_data) {tBTA_HF_CLIENT_CB* client_cb =bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);if (client_cb == NULL) {APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,p_data->hdr.layer_specific);return;}uint16_t len;char buf[BTA_HF_CLIENT_RFC_READ_MAX];memset(buf, 0, sizeof(buf));/* read data from rfcomm; if bad status, we're done */while (PORT_ReadData(client_cb->conn_handle, buf, BTA_HF_CLIENT_RFC_READ_MAX,&len) == PORT_SUCCESS) {/* if no data, we're done */if (len == 0) {break;}bta_hf_client_at_parse(client_cb, buf, len);/* no more data to read, we're done */if (len < BTA_HF_CLIENT_RFC_READ_MAX) {break;}}
}
bta_hf_client_at_parse(client_cb, buf, len);

队列里的HF client函数处理表:由void bta_hf_client_sm_execute(uint16_t event, tBTA_HF_CLIENT_DATA* p_data) 调度处理

/* action functions table, indexed with action enum */
const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = {/* BTA_HF_CLIENT_RFC_DO_CLOSE */ bta_hf_client_rfc_do_close,/* BTA_HF_CLIENT_START_CLOSE */ bta_hf_client_start_close,/* BTA_HF_CLIENT_START_OPEN */ bta_hf_client_start_open,/* BTA_HF_CLIENT_RFC_ACP_OPEN */ bta_hf_client_rfc_acp_open,/* BTA_HF_CLIENT_SCO_LISTEN */ NULL,/* BTA_HF_CLIENT_SCO_CONN_OPEN */ bta_hf_client_sco_conn_open,/* BTA_HF_CLIENT_SCO_CONN_CLOSE*/ bta_hf_client_sco_conn_close,/* BTA_HF_CLIENT_SCO_OPEN */ bta_hf_client_sco_open,/* BTA_HF_CLIENT_SCO_CLOSE */ bta_hf_client_sco_close,/* BTA_HF_CLIENT_FREE_DB */ bta_hf_client_free_db,/* BTA_HF_CLIENT_OPEN_FAIL */ bta_hf_client_open_fail,/* BTA_HF_CLIENT_RFC_OPEN */ bta_hf_client_rfc_open,/* BTA_HF_CLIENT_RFC_FAIL */ bta_hf_client_rfc_fail,/* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res,/* BTA_HF_CLIENT_RFC_DO_OPEN */ bta_hf_client_rfc_do_open,/* BTA_HF_CLIENT_DISC_FAIL */ bta_hf_client_disc_fail,/* BTA_HF_CLIENT_RFC_CLOSE */ bta_hf_client_rfc_close,/* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data,/* BTA_HF_CLIENT_DISC_ACP_RES */ bta_hf_client_disc_acp_res,/* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open,/* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd,
};

手机连蓝牙音箱,手机向外打电话

01-01 08:40:00.215   900  1290 D HeadsetClientStateMachine: Connected process message: 100
01-01 08:40:00.216   900  1290 D HeadsetClientStateMachine: Connected: event type: 16
01-01 08:40:00.216   900  1290 D HeadsetClientStateMachine: Connected: command result: 0 queuedAction: 50
01-01 08:40:00.216   900  1290 D HeadsetClientStateMachine: queryCallsDone
01-01 08:40:00.217   900  1290 D HeadsetClientStateMachine: currCallIdSet [] newCallIdSet [1] callAddedIds [1] callRemovedIds [] callRetainedIds []
01-01 08:40:00.217   900  1290 D HeadsetClientStateMachine: ADJUST: currCallIdSet [] newCallIdSet [1] callAddedIds [1] callRemovedIds [] callRetainedIds []
01-01 08:40:00.218   900  1290 D HeadsetClientStateMachine: sendCallChangedIntent BluetoothHeadsetClientCall{mDevice: 331361095, mId: 1, mUUID: d13e321f-b7dd-4015-98d3-f4c2c2d8fa4c, mState: ALERTING, mNumber: 46730415, mMultiParty: false, mOutgoing: true}
01-01 08:40:00.224   900   900 D HfpClientConnService: onReceive Intent { act=android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED flg=0x10000010 (has extras) }
01-01 08:40:00.225   900   900 D HfpClientConnService: Finding block for device 50:8F:4C:F9:F1:67 blocks {50:8F:4C:F9:F1:67=com.android.bluetooth.hfpclient.connserv.HfpClientDeviceBlock@f6f925c}
01-01 08:40:00.225   900   900 D HfpClientDeviceBlock.50:8F:4C:F9:F1:67: Got call BluetoothHeadsetClientCall{mDevice: 50:8F:4C:F9:F1:67, mId: 1, mUUID: d13e321f-b7dd-4015-98d3-f4c2c2d8fa4c, mState: ALERTING, mNumber: 10086, mMultiParty: false, mOutgoing: true}
01-01 08:40:00.225   900   900 D HfpClientDeviceBlock.50:8F:4C:F9:F1:67: findConnectionKey local key set {}
01-01 08:40:00.226   900   900 D HfpClientDeviceBlock.50:8F:4C:F9:F1:67: Creating connection on 50:8F:4C:F9:F1:67 for BluetoothHeadsetClientCall{mDevice: 331361095, mId: 1, mUUID: d13e321f-b7dd-4015-98d3-f4c2c2d8fa4c, mState: ALERTING, mNumber: 46730415, mMultiParty: false, mOutgoing: true}/null
01-01 08:40:00.234   900   900 D HfpClientConnection: Got call state change to 3
01-01 08:40:00.235   900   900 D BluetoothHeadsetClient: getCurrentCalls()
01-01 08:40:00.243   900   900 D HeadsetClientService: Found SM for device 50:8F:4C:F9:F1:67

AG_CALL_CHANGED

在这里插入图片描述

 case StackEvent.STACK_EVENT:Intent intent = null;StackEvent event = (StackEvent) message.obj;if (DBG) {Log.d(TAG, "Connected: event type: " + event.type);}

                       case StackEvent.EVENT_TYPE_CMD_RESULT:Pair<Integer, Object> queuedAction = mQueuedActions.poll();// should not happen but...if (queuedAction == null || queuedAction.first == NO_ACTION) {clearPendingAction();break;}if (DBG) {Log.d(TAG, "Connected: command result: " + event.valueInt+ " queuedAction: " + queuedAction.first);}switch (queuedAction.first) {case QUERY_CURRENT_CALLS:queryCallsDone();break;default:Log.w(TAG, "Unhandled AT OK " + event);break;}break;


queryCallsDone

在这里插入图片描述|

    private void sendCallChangedIntent(BluetoothHeadsetClientCall c) {Log.d(TAG, "Enter sendCallChangedIntent()");if (DBG) {Log.d(TAG, "sendCallChangedIntent " + c);}Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CALL_CHANGED);intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);intent.putExtra(BluetoothHeadsetClient.EXTRA_CALL, c);mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);Log.d(TAG, "Exit sendCallChangedIntent()");}
|

终于发出了ACTION_CALL_CHANGED

接收广播
在这里插入图片描述

进入outgoing电话
在这里插入图片描述手机连接车机,车机打电话的的流程

车机通过ATD10086告诉手机车机要打的号码,通过手机后手机向外打电话,手机返回ok后,车机开机查询手机的通话状态或者手机通过ciev事件告诉车机状态
在这里插入图片描述
两个角色互发数据的数据流程

作为AG角色:接收发送命令的接口
处理HF角色发来的命令
在这里插入图片描述
bta_ag_reg =>> bta_ag_hdl_event ==>> bta_ag_sm_execute ==>>bta_ag_rfc_data ==>>bta_ag_at_parse ==>>bta_ag_process_at
调用注册的callback函数 bta_ag_at_hfp_cback

发送消息给HF **
这个处理函数中调用的大多为
bta_ag_send_result**,然后bta_ag_send_result调用PORT_WriteData向rfcomm给对方传数据

作为HF 角色:接收发送命令的接口
发送命令给AG : bta_hf_client_send_at 
处理来自AG角色发来的命令:bta_hf_client_rfc_data==>PORT_ReadData bta_hf_client_at_parse==>bta_hf_client_at_parse_start=>
bta_hf_client_parser_cb
在这里插入图片描述
如处理CIEV事件:
bta_hf_client_parse_ciev
=>bta_hf_client_handle_ciev
==>bta_hf_client_ind
====>bta_hf_client_app_callback(BTA_HF_CLIENT_IND_EVT, &evt);
===>btif_hf_client_upstreams_evt可以查看到很多抛到上层的事件
 process_ind_evt(&p_data->ind);
 在这里插入图片描述

**修改HF的版本号**
diff --git a/system/bt/bta/hf_client/bta_hf_client_sdp.cc b/system/bt/bta/hf_client/bta_hf_client_sdp.cc
index 475ce16..8ae2a36 100644
--- a/system/bt/bta/hf_client/bta_hf_client_sdp.cc
+++ b/system/bt/bta/hf_client/bta_hf_client_sdp.cc
@@ -117,7 +117,7 @@ bool bta_hf_client_add_record(const char* p_service_name, uint8_t scn,/* add profile descriptor list */profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
-  version = HFP_VERSION_1_6;
+  version = HFP_VERSION_1_5;result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);

修改HF的feature
./btif/src/btif_hf_client.cc

#ifndef BTIF_HF_CLIENT_FEATURES
#define BTIF_HF_CLIENT_FEATURES                                                \(BTA_HF_CLIENT_FEAT_ECNR | BTA_HF_CLIENT_FEAT_3WAY |                         \BTA_HF_CLIENT_FEAT_CLI | BTA_HF_CLIENT_FEAT_VREC | BTA_HF_CLIENT_FEAT_VOL | \BTA_HF_CLIENT_FEAT_ECS | BTA_HF_CLIENT_FEAT_ECC | BTA_HF_CLIENT_FEAT_CODEC)
#endif

去掉BTA_HF_CLIENT_FEAT_CODEC,不支持编解码协商,结合hf1.5,车机端默认为cvsd解码
在这里插入图片描述
电量显示支持

在这里插入图片描述
Android状态栏显示蓝牙耳机电量
在这里插入图片描述

安卓蓝牙支持苹果耳机,需要定制,如电池电量 AT+IPHONEACCEV

描述:报告耳机的状态变更
发起者:耳机
格式:AT+IPHONEACCEV=[Number of key/value pairs ],[key1 ],[val1 ],[key2 ],[val2 ],...
参数:Number of key/value pairs : 接下来参数的数量key: 被报告状态变化的类型1 = 电量等级2 = 暂停状态val: 更改的值Battery events:0-9之间数字的字符串 A string value between '0' and '9'.Dock state: 0 = undocked, 1 = docked.
Example: AT+IPHONEACCEV=1,1,3


AT+XAPL
+XAPL
AT+IPHONEACCEV
在这里插入图片描述
命令当作一个错误上抛到应用层处理:
bta_ag_at_err_cback-》BTA_AG_AT_UNAT_EVT:unknown_at_cmd_cb-》unknown_at_callback-》onUnknownAt-》processUnknownAt->processVendorSpecificAt->broadcastVendorSpecificEventIntent->onVendorSpecificHeadsetEvent->
VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV:getBatteryLevelFromAppleBatteryVsc->updateBatteryLevel->
sendBatteryLevelChangedBroadcast->ACTION_BATTERY_LEVEL_CHANGED->BatteryLevelChangedHandler->

在这里插入图片描述
在这里插入图片描述
默认HFP协议中是AG给HF电量,profile中是没有定义HF给AG电量,所以各家都有扩展,QCC是扩展的BIEV,然后iphone是扩展的AT+IPHONEACCEV,各个耳机遵循的不同,看方案·
在这里插入图片描述
处理BIEV的流程:

Bluetooth\src\com\android\bluetooth\hfp\HeadsetStateMachine.java

processAtBiev
sendIndicatorIntent
onHfIndicatorValueChanged
updateBatteryLevel
打电话:
BluetoothHeadsetClientCall dial
HeadsetClientService BluetoothHeadsetClientCall dial(BluetoothDevice device, String number)
mNativeInterface.dialNative 发给对方手机
然后发送sendMessage(QUERY_CURRENT_CALLS);检测手机的通话状态,最后将手机的电话状态HfpClientConnection告诉本地的手机c通讯模块

HCI_Disconnection_Complete断开事件有一个connect handle,如果是esco断开它采用的connect handle与基于acl的connnect handle断开,两者的connect handle是不同的,与此来判断是sco断开还是acl断开 ,下面是sco生成的handle
在这里插入图片描述正常通讯的handle
在这里插入图片描述
由上可知不同,也由此可知以下的断开是esco的断开,而非acl的断开
在这里插入图片描述

rfcomm接收数据

将从对端的数据放在队列中

void btu_hci_msg_process(BT_HDR* p_msg) {/* Determine the input message type. */switch (p_msg->event & BT_EVT_MASK) {case BT_EVT_TO_BTU_HCI_ACL:/* All Acl Data goes to L2CAP */l2c_rcv_acl_data(p_msg);break;

l2c_rcv_acl_data

l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);

case CST_OPEN:
l2c_csm_open(p_ccb, event, p_data);

l2c_csm_open->

case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd    */if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb))(*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid,(BT_HDR*)p_data);break;
数据从l2cap 的BT_PSM_RFCOMM通道中上来p_l2c->pL2CA_DataInd_Cb = RFCOMM_BufDataInd;L2CA_Register(BT_PSM_RFCOMM, p_l2c);

RFCOMM_BufDataInd

rfc_parse_data解析事件类型

if (event == RFC_EVENT_UIH) {
if (p_buf->len > 0)
rfc_port_sm_execute(p_port, event, p_buf);
else
osi_free(p_buf);

case RFC_STATE_OPENED:rfc_port_sm_opened(p_port, event, p_data);

rfc_port_sm_opened->

case RFC_EVENT_UIH:rfc_port_uplink_data(p_port, (BT_HDR*)p_data);

rfc_port_uplink_data
->PORT_DataInd-> fixed_queue_enqueue(p_port->rx.queue, p_buf);
-> if (p_port->p_callback && events) p_port->p_callback(events, p_port->inx);通知上层读数据

上层取从队列中数据
-------------------------------------------------------------
p_port->p_callback接口注册流程

HF CLIENT:

bta_hf_client_port_cback-> p_buf->hdr.event = BTA_HF_CLIENT_RFC_DATA_EVT;


//在
bta_hf_client_do_disc ->   db_inited = SDP_ServiceSearchAttributeRequest2(client_cb->peer_addr, client_cb->p_disc_db, bta_hf_client_sdp_cback,(void*)client_cb);bta_hf_client_sdp_cback->     event = BTA_HF_CLIENT_DISC_INT_RES_EVT;bta_hf_client_disc_int_res->      event = BTA_HF_CLIENT_DISC_OK_EVT;/* DISC_OK_EVT */ {BTA_HF_CLIENT_RFC_DO_OPEN, BTA_HF_CLIENT_IGNORE,BTA_HF_CLIENT_OPENING_ST},bta_hf_client_rfc_do_open->PORT_SetEventCallback(handle, bta_hf_client_port_cback);中注册

-------------------------------------------------------------

即 p_port->p_callback = bta_hf_client_port_cback

在这里插入图片描述
搜索部分RFC_DATA得到结果

/* RFC_DATA_EVT */ {BTA_HF_CLIENT_RFC_DATA, BTA_HF_CLIENT_IGNORE,
BTA_HF_CLIENT_OPEN_ST},

搜索BTA_HF_CLIENT_RFC_DATA
bta_hf_client_main.cc (bta\hf_client) line 96 : /* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data,

bta_hf_client_rfc_data ->

hf AG:
bta_ag_rfc_data
hf CLIENT:
bta_hf_client_rfc_data

PORT_Read ->
p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue);

解析命令,再回传给上层
bta_hf_client_at_parse(client_cb, buf, len);->bta_hf_client_at_parse_start->bta_hf_client_parser_cb->

static const tBTA_HF_CLIENT_PARSER_CALLBACK bta_hf_client_parser_cb[] = {bta_hf_client_parse_ok,          bta_hf_client_parse_error,bta_hf_client_parse_ring,        bta_hf_client_parse_brsf,bta_hf_client_parse_cind,        bta_hf_client_parse_ciev,bta_hf_client_parse_chld,        bta_hf_client_parse_bcs,bta_hf_client_parse_bsir,        bta_hf_client_parse_cmeerror,bta_hf_client_parse_vgm,         bta_hf_client_parse_vgme,bta_hf_client_parse_vgs,         bta_hf_client_parse_vgse,bta_hf_client_parse_bvra,        bta_hf_client_parse_clip,bta_hf_client_parse_ccwa,        bta_hf_client_parse_cops,bta_hf_client_parse_binp,        bta_hf_client_parse_clcc,bta_hf_client_parse_cnum,        bta_hf_client_parse_btrh,bta_hf_client_parse_busy,        bta_hf_client_parse_delayed,bta_hf_client_parse_no_carrier,  bta_hf_client_parse_no_answer,bta_hf_client_parse_blacklisted, bta_hf_client_skip_unknown};

获取电话号码:

HeadsetClientStateMachine.java

processConnectionEvent

case HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED:
sendMessage(HeadsetClientStateMachine.SUBSCRIBER_INFO);

      if (NativeInterface.retrieveSubscriberInfoNative(getByteAddress(mCurrentDevice))) {addQueuedAction(SUBSCRIBER_INFO);}

sBluetoothHfpClientInterface->retrieve_subscriber_info

static bt_status_t retrieve_subscriber_info(const RawAddress* bd_addr) {btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CNUM, 0, 0, NULL);return BT_STATUS_SUCCESS;
}

这样hf client就发送命令出去了

手机这边接收到命令后

/* AT command interpreter table for HFP */
const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] = {{"A", BTA_AG_AT_A_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},{"D", BTA_AG_AT_D_EVT, BTA_AG_AT_NONE | BTA_AG_AT_FREE, BTA_AG_AT_STR, 0,0},{"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},{"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},{"+CCWA", BTA_AG_LOCAL_EVT_CCWA, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},/* Consider CHLD as str to take care of indexes for ECC */{"+CHLD", BTA_AG_AT_CHLD_EVT, BTA_AG_AT_SET | BTA_AG_AT_TEST, BTA_AG_AT_STR,0, 4},{"+CHUP", BTA_AG_AT_CHUP_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},{"+CIND", BTA_AG_AT_CIND_EVT, BTA_AG_AT_READ | BTA_AG_AT_TEST,BTA_AG_AT_STR, 0, 0},{"+CLIP", BTA_AG_LOCAL_EVT_CLIP, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},{"+CMER", BTA_AG_LOCAL_EVT_CMER, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},{"+VTS", BTA_AG_AT_VTS_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},{"+BINP", BTA_AG_AT_BINP_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 1, 1},{"+BLDN", BTA_AG_AT_BLDN_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},{"+BVRA", BTA_AG_AT_BVRA_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},{"+BRSF", BTA_AG_LOCAL_EVT_BRSF, BTA_AG_AT_SET, BTA_AG_AT_INT, 0,BTA_AG_CMD_MAX_VAL},{"+NREC", BTA_AG_AT_NREC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 0},{"+CNUM", BTA_AG_AT_CNUM_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},{"+BTRH", BTA_AG_AT_BTRH_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_INT,0, 2},{"+CLCC", BTA_AG_AT_CLCC_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},{"+COPS", BTA_AG_AT_COPS_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_STR,0, 0},{"+CMEE", BTA_AG_LOCAL_EVT_CMEE, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},{"+BIA", BTA_AG_LOCAL_EVT_BIA, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},{"+CBC", BTA_AG_AT_CBC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100},{"+BCC", BTA_AG_LOCAL_EVT_BCC, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},{"+BCS", BTA_AG_AT_BCS_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0,BTA_AG_CMD_MAX_VAL},{"+BIND", BTA_AG_AT_BIND_EVT,BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0},{"+BIEV", BTA_AG_AT_BIEV_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},{"+BAC", BTA_AG_AT_BAC_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},/* End-of-table marker used to stop lookup iteration */{"", 0, 0, 0, 0, 0}};

case BTA_AG_AT_CNUM_EVT:
HAL_CBACK(bt_hf_callbacks, cnum_cmd_cb, &btif_hf_cb[idx].connected_bda);

static bthf_callbacks_t sBluetoothHfpCallbacks = {sizeof(sBluetoothHfpCallbacks),connection_state_callback,audio_state_callback,voice_recognition_callback,answer_call_callback,hangup_call_callback,volume_control_callback,dial_call_callback,dtmf_cmd_callback,noice_reduction_callback,wbs_callback,at_chld_callback,at_cnum_callback,at_cind_callback,at_cops_callback,at_clcc_callback,unknown_at_callback,at_bind_callback,at_biev_callback,key_pressed_callback};

at_cnum_callback

HeadsetStateMachine.java
private void onAtCnum(byte[] address) {
StackEvent event = new StackEvent(EVENT_TYPE_SUBSCRIBER_NUMBER_REQUEST);
event.device = getDevice(address);
sendMessage(STACK_EVENT, event);
}

   case EVENT_TYPE_SUBSCRIBER_NUMBER_REQUEST:processSubscriberNumberRequest(event.device);

processSubscriberNumberRequest
在这里插入图片描述

SLC连接建立
https://blog.csdn.net/shichaog/article/details/52123439
BTA_EnableBluetooth->BTA_DM_API_ENABLE_EVT

bta_dm_enable

btif_dm_upstreams_evt
case BTA_DM_ENABLE_EVT: {
btif_in_execute_service_request

case BTA_HFP_HS_SERVICE_ID: {btif_hf_client_execute_service(b_enable);

BTA_HfClientEnable

bta_hf_client_api_enable

bta_hf_client_start_server
RFCOMM_CreateConnection(
UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb_arr.scn, true,
BTA_HF_CLIENT_MTU, RawAddress::kAny, &(bta_hf_client_cb_arr.serv_handle),
bta_hf_client_mgmt_cback);

    bta_hf_client_setup_port(bta_hf_client_cb_arr.serv_handle);
void bta_hf_client_setup_port(uint16_t handle) {PORT_SetEventMask(handle, PORT_EV_RXCHAR);PORT_SetEventCallback(handle, bta_hf_client_port_cback);
}

在这里插入图片描述
处理BTA_HF_CLIENT_RFC_DATA_EVT
在这里插入图片描述rfcomm连接上执行call函数bta_hf_client_mgmt_cback

bta_hf_client_mgmt_cback

bta_hf_client_rfc_acp_open

bta_hf_client_rfc_open
bta_sys_conn_open
bta_hf_client_slc_seq刚开始初始值为BTA_HF_CLIENT_AT_NONE
在这里插入图片描述
一次对话过后有一个OK返回,由bta_hf_client_handle_ok处理,启动下一次命令
在这里插入图片描述
client_cb->svc_conn在SLC连接成功后为true
在这里插入图片描述
SLC连接成功了
bta_hf_client_svc_conn_open->
BTA_HF_CLIENT_CONN_EVT

case BTA_HF_CLIENT_CONN_EVT:cb->peer_feat = p_data->conn.peer_feat;cb->chld_feat = p_data->conn.chld_feat;cb->state = BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED;HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,cb->state, cb->peer_feat, cb->chld_feat);

在这里插入图片描述
从日志分析,at+cmer+at+chld执行完后就slc建立成功了
在这里插入图片描述

hf client disconnect

disconnect->BTA_HfClientClose->BTA_HF_CLIENT_API_CLOSE_EVT->bta_hf_client_start_close

查找方法,正常情況下工作是open狀態,根据BTA_ID_HS找注册函数 先找准状态,再此找事件为对应状态的下标BTA_HF_CLIENT_API_CLOSE_EVT即第二个,则为API_CLOSE_EVT,查找BTA_HF_CLIENT_START_CLOSE其实换成小写就是,即bta_hf_client_start_close
enum {
/* these events are handled by the state machine */
BTA_HF_CLIENT_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HS),
BTA_HF_CLIENT_API_CLOSE_EVT,

在这里插入图片描述

01-02 14:03:14.417387  7674  7713 I bt_btif : bta_sys_event: Event 0x1b01
01-02 14:03:14.417480  7674  7713 D bt_btif : bta_hf_client_hdl_event: BTA_HF_CLIENT_API_CLOSE_EVT (0x1b01)
01-02 14:03:14.417532  7674  7713 I bt_btif : HF Client evt : State 2 (BTA_HF_CLIENT_OPEN_ST), Event 0x1b01 (BTA_HF_CLIENT_API_CLOSE_EVT)

bta_hf_client_start_close :
bta_hf_client_rfc_do_close->
RFCOMM_RemoveConnection
BTA_HF_CLIENT_RFC_CLOSE_EVT->
SDP_CancelServiceSearch
其中

	 /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE,bta_hf_client_rfc_close										 

bta_hf_client_rfc_close
bta_hf_client_at_reset
bta_sys_conn_close
bta_hf_client_sco_shutdown->bta_hf_client_sco_remove->BTM_RemoveSco
bta_sys_sco_unuse在这里插入图片描述

来电状态判断:
跟据发送的ACTION_CALL_CHANGED所携带的BluetoothHeadsetClientCall状态来判断通话情况
HeadsetClientStateMachine: sendCallChangedIntent BluetoothHeadsetClientCall{mDevice: 12668044, mId: 1, mUUID: cb3fc521-a8d5-4ff0-90d9-627bfd276a68, mState: INCOMING, mNumber: -1567968462, mMultiParty: false, mOutgoing: false}

12-16 10:43:52.167   897  1290 D HeadsetClientStateMachine: ADJUST: currCallIdSet [1] newCallIdSet [1] callAddedIds [] callRemovedIds [] callRetainedIds [1]
12-16 10:43:52.167   897  1290 D HeadsetClientStateMachine: sendCallChangedIntent BluetoothHeadsetClientCall{mDevice: 12668044, mId: 1, mUUID: cb3fc521-a8d5-4ff0-90d9-627bfd276a68, mState: INCOMING, mNumber: -1567968462, mMultiParty: false, mOutgoing: false}
12-16 10:43:52.676   897  1290 D HeadsetClientStateMachine: AudioOn process message: 50
12-16 10:43:52.676   897  1290 D HeadsetClientStateMachine: Connected process message: 50
12-16 10:43:52.676   897  1290 D HeadsetClientStateMachine: queryCallsStart
12-16 10:43:52.798   897  1290 D HeadsetClientStateMachine: AudioOn process message: 100
12-16 10:43:52.798   897  1290 D HeadsetClientStateMachine: AudioOn: event type: 14
12-16 10:43:52.798   897  1290 D HeadsetClientStateMachine: Connected process message: 100
12-16 10:43:52.798   897  1290 D HeadsetClientStateMachine: Connected: event type: 14
12-16 10:43:52.798   897  1290 D HeadsetClientStateMachine: queryCallsUpdate: 1
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: AudioOn process message: 100
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: AudioOn: event type: 16
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: Connected process message: 100
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: Connected: event type: 16
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: Connected: command result: 0 queuedAction: 50
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: queryCallsDone
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: currCallIdSet [1] newCallIdSet [1] callAddedIds [] callRemovedIds [] callRetainedIds [1]
12-16 10:43:52.801   897  1290 D HeadsetClientStateMachine: ADJUST: currCallIdSet [1] newCallIdSet [1] callAddedIds [] callRemovedIds [] callRetainedIds [1]
12-16 10:43:52.802   897  1290 D HeadsetClientStateMachine: sendCallChangedIntent BluetoothHeadsetClientCall{mDevice: 12668044, mId: 1, mUUID: cb3fc521-a8d5-4ff0-90d9-627bfd276a68, mState: INCOMING, mNumber: -1567968462, mMultiParty: false, mOutgoing: false}
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: AudioOn process message: 100
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: AudioOn: event type: 10
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: Connected process message: 100
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: Connected: event type: 10
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: AudioOn process message: 50
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: Connected process message: 50
12-16 10:43:53.256   897  1290 D HeadsetClientStateMachine: queryCallsStart
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: AudioOn process message: 100
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: AudioOn: event type: 16
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: Connected process message: 100
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: Connected: event type: 16
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: Connected: command result: 0 queuedAction: 50
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: queryCallsDone
12-16 10:43:53.340   897  1290 D HeadsetClientStateMachine: currCallIdSet [1] newCallIdSet [] callAddedIds [] callRemovedIds [1] callRetainedIds []
12-16 10:43:53.341   897  1290 D HeadsetClientStateMachine: ADJUST: currCallIdSet [1] newCallIdSet [] callAddedIds [] callRemovedIds [1] callRetainedIds []
12-16 10:43:53.341   897  1290 D HeadsetClientStateMachine: sendCallChangedIntent BluetoothHeadsetClientCall{mDevice: 12668044, mId: 1, mUUID: cb3fc521-a8d5-4ff0-90d9-627bfd276a68, mState: TERMINATED, mNumber: -1567968462, mMultiParty: false, mOutgoing: false}
12-16 10:43:55.390   897  1290 D HeadsetClientStateMachine: AudioOn process message: 100
12-16 10:43:55.390   897  1290 D HeadsetClientStateMachine: AudioOn: event type: 2
12-16 10:43:55.390   897  1290 D HeadsetClientStateMachine: AudioOn audio state changed38:71:DE:2B:46:2B: 0
12-16 10:43:55.390   897  1290 D HeadsetClientStateMachine: hfp_enable=false
12-16 10:43:55.549   897  1290 D HeadsetClientStateMachine: Audio state 38:71:DE:2B:46:2B: 2->0
12-16 10:43:55.549   897  1290 D HeadsetClientStateMachine: Exit AudioOn: 100
12-16 10:43:55.549   897  1290 D HeadsetClientStateMachine: Exit Connected: 100
12-16 10:43:55.549   897  1290 D HeadsetClientStateMachine: Enter Connected: 100
12-16 10:43:55.573   897  1290 D HeadsetClientStateMachine: Connected process message: 100
12-16 10:43:55.573   897  1290 D HeadsetClientStateMachine: Connected: event type: 6
12-16 10:44:21.919   897  1290 D HeadsetClientStateMachine: Connected process message: 100

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/626.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息