拨打电话通过蓝牙接通

来源:互联网 发布:python 分析谁是小偷 编辑:程序博客网 时间:2024/05/01 18:59

我配对号蓝牙耳机,然后拨打电话,接通后,声音会从蓝牙耳机里面出来,这个流程是怎么样的呢?今天就来分析。

     首先肯定的是在开启蓝牙通话的这个通道是在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 )
    {

一些蓝牙不能传出声音很有可能就是这里出现了问题!