AVRCP连接状态异常
安卓版本:android-9(P版本)
问题现象:断开设备,迟迟没有发出BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED的广播将连接状态切到 BluetoothAdapter.STATE_DISCONNECTED
查看log可以发现各个主要协议都断开完成,那为何上述广播没有及时发出去呢?
该广播是在 AdapterProperties.sendConnectionStateChange() 中触发的,没有触发说明if条件不满足
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
int newAdapterState = convertToAdapterState(state);
int prevAdapterState = convertToAdapterState(prevState);
setConnectionState(newAdapterState);
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, newAdapterState);
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, prevAdapterState);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Log.i(TAG, "ADAPTER_CONNECTION_STATE_CHANGE: " + device + ": " + prevAdapterState
+ " -> " + newAdapterState);
if (!isNormalStateTransition(prevState, state)) {
Log.w(TAG, "ADAPTER_CONNECTION_STATE_CHANGE: unexpected transition for profile="
+ profile + ", device=" + device + ", " + prevState + " -> " + state);
}
mService.sendBroadcastAsUser(intent, UserHandle.ALL, AdapterService.BLUETOOTH_PERM);
}
updateCountersAndCheckForConnectionStateChange() 函数在断开设备阶段只有连接的全部协议都断开完成才会返回true,如此说明还有协议没有断开,再结合log基本锁定avrcp协议没有断开。
Avrcp协议的连接断开完全是跟着A2DP协议走的,log显示断avrcp完成时协议栈没有连接记录,btif_rc_get_device_by_handle() 返回NULL。
那就说明avrcp根本就没连接上,那为何蓝牙服务层会保存有avrcp连接成功的状态呢?
继续分析前面A2DP连接后SINK端主动连接avrcp的流程,a2dp连接的状态机为 StateOpening 时收到 BTA_AV_OPEN_EVT 事件中调用 BTA_AvOpenRc() 触发avrcp的连接。
协议连接首先进行SDP服务发现,从log也可以看到以 psm= 0x0001 去创建了一条l2cap链路。
这条l2cap链路请求连接时对端回复PEER_CONNECT_RSP_NEG拒绝掉了,从而avrcp协议连接失败
重点来了,avrcp都连接失败了为何还上报了连接成功的状态到服务层,一脸懵逼。。。
跟踪 handle_rc_connect() 处理函数,发现代码中对失败的处理有问题,不管成功失败总是会上报连接成功的状态到上层
问题到这儿就很清楚了,由于上述函数处理失败情况存在问题导致蓝牙服务层和协议栈对avrcp的连接状态不匹配,最终导致在后续的断开设备时,服务层始终认为 avrcp 协议连接状态为CONNECTED,从而不会对外发出 BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED 断开完成的广播。感兴趣的小伙伴欢迎私信留言一起讨论,共同学习,一起进步!
更多互联互通技术,欢迎关注微信公众号:Connectivity