我配对号蓝牙耳机,然后拨打电话,接通后,声音会从蓝牙耳机里面出来,这个流程是怎么样的呢?今天就来分析。
首先肯定的是在开启蓝牙通话的这个通道是在Phone进程里面。
APP层核文件:
BluetoothHandsfree.java
接通开通蓝牙的通话通道不是在Incscreen,而是在这个BluetoothHandsfree内部类BluetoothPhoneState类里面注册了一个广播的监听器来监听电话的状态:
代码片段:
case PRECISE_CALL_STATE_CHANGED:
case PHONE_CDMA_CALL_WAITING:
Connection connection = null;
if (((AsyncResult) msg.obj).result instanceof Connection) {
connection = (Connection) ((AsyncResult) msg.obj).result;
}
handlePreciseCallStateChange(sendUpdate(), connection);
当Phone处于Dialing状态的时候就会去建立连接。
流程:handlePreciseCallStateChange---->audioOn();--->mHeadset.connect() (mHeadset在原生态代码中为BluetoothAudioGateway,在MTK平台中为HeadsetBase,但实现的效果都一样)
Framework:
(BluetoothAudioGateway或则BluetoothAudioGateway)connect--->connectNative()---->connectNative()(android_bluetooth_BluetoothAudioGateway)----->
当系统建立连接后就会通过BluetoothHeadsetService来通知BluetoothAudioGateway进行出里。
BluetoothHeadsetService中的代码片段:
case BluetoothAudioGateway.SCO_ACCEPTED:
case BluetoothAudioGateway.SCO_CONNECTED:
case BluetoothAudioGateway.SCO_CLOSED:
if(msg.obj == null) {
logWarn("Remote Device is null when receive SCO msg");
mBtHandsfree.handleSCOEvent(msg.what, null);
BluetoothAudioGateway:
handleSCOEvent--->mAudioManager.setBluetoothScoOn(true);---->AudioManager----->AudioService
AudioService:
setBluetoothScoOn代码片段:
public void setBluetoothScoOn(boolean on){
if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
return;
}
mForcedUseForComm = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
Log.d(TAG, "setBluetoothScoOn " + mForcedUseForComm);
}
注意这里发送了两次消息。猜测两次的目的是一次是告诉系统我要使用的是通话功能,二次是告诉系统录音功能,因为通话的时候应该是可以录音的,如果把第二次For_RECORD去掉,应该是也能成功设置的。
setForceUse---> AudioSystem.setForceUse------>AudioSystem::setForceUse-------->AudioPolicyService::setForceUse------->AudioYusuPolicyManager::setForceUse
AudioYusuPolicyManager:
这里面有个很重要的位置判断:
if(AudioSystem::popCount(newDevice) != 2 )
{
一些蓝牙不能传出声音很有可能就是这里出现了问题!