startBluetoothSco和setBluetoothScoOn流程

 
​
@frameworks/base/media/java/android/media/AudioManager.java
    public void startBluetoothSco(){
        IAudioService service = getService();
        try {
            service.startBluetoothSco(mICallBack,
                    getContext().getApplicationInfo().targetSdkVersion);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in startBluetoothSco", e);
        }
    }

startBluetoothSco@frameworks/base/services/core/java/com/android/server/audio/AudioService.java 

    /** @see AudioManager#startBluetoothSco() */
    public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
        int scoAudioMode =
                (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
                        SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
        startBluetoothScoInt(cb, scoAudioMode);
    }

@frameworks/base/services/core/java/com/android/server/audio/AudioService.java
    void startBluetoothScoInt(IBinder cb, int scoAudioMode){
        if (!checkAudioSettingsPermission("startBluetoothSco()") ||
                !mSystemReady) {
            return;
        }
        ScoClient client = getScoClient(cb, true);
        // The calling identity must be cleared before calling ScoClient.incCount().
        // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
        // and this must be done on behalf of system server to make sure permissions are granted.
        // The caller identity must be cleared after getScoClient() because it is needed if a new
        // client is created.
        final long ident = Binder.clearCallingIdentity();
        client.incCount(scoAudioMode);
        Binder.restoreCallingIdentity(ident);
    }



@frameworks/base/services/core/java/com/android/server/audio/AudioService.java
        public void incCount(int scoAudioMode) {
            synchronized(mScoClients) {
                requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
                if (mStartcount == 0) {
                    try {
                        mCb.linkToDeath(this, 0);
                    } catch (RemoteException e) {
                        // client has already died!
                        Log.w(TAG, "ScoClient  incCount() could not link to "+mCb+" binder death");
                    }
                }
                mStartcount++;
            }
        }




        private void requestScoState(int state, int scoAudioMode) {
            checkScoAudioState();
            if (totalCount() == 0) {
                if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
                    // Make sure that the state transitions to CONNECTING even if we cannot initiate
                    // the connection.
                    broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
                    // Accept SCO audio activation only in NORMAL audio mode or if the mode is
                    // currently controlled by the same client process.
                    synchronized(mSetModeDeathHandlers) {
                        if ((mSetModeDeathHandlers.isEmpty() ||
                                mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
                                (mScoAudioState == SCO_STATE_INACTIVE ||
                                 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
                            if (mScoAudioState == SCO_STATE_INACTIVE) {
                                mScoAudioMode = scoAudioMode;
                                if (scoAudioMode == SCO_MODE_UNDEFINED) {
                                    if (mBluetoothHeadsetDevice != null) {
                                        mScoAudioMode = new Integer(Settings.Global.getInt(
                                                                mContentResolver,
                                                                "bluetooth_sco_channel_"+
                                                                mBluetoothHeadsetDevice.getAddress(),
                                                                SCO_MODE_VIRTUAL_CALL));
                                        if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
                                            mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
                                        }
                                    } else {
                                        mScoAudioMode = SCO_MODE_RAW;
                                    }
                                }
                                if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
                                    boolean status = false;
                                    if (mScoAudioMode == SCO_MODE_RAW) {
                                        status = mBluetoothHeadset.connectAudio();
                                    } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
                                        status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
                                                                            mBluetoothHeadsetDevice);
                                    } else if (mScoAudioMode == SCO_MODE_VR) {
                                        status = mBluetoothHeadset.startVoiceRecognition(
                                                                           mBluetoothHeadsetDevice);
                                    }

                                    if (status) {
                                        mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
                                    } else {
                                        broadcastScoConnectionState(
                                                AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                                    }
                                } else if (getBluetoothHeadset()) {
                                    mScoAudioState = SCO_STATE_ACTIVATE_REQ;
                                }
                            } else {
                                mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
                                broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
                            }
                        } else {
                            broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                        }
                    }
                } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
                              (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
                               mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
                    if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
                        if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
                            boolean status = false;
                            if (mScoAudioMode == SCO_MODE_RAW) {
                                status = mBluetoothHeadset.disconnectAudio();
                            } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
                                status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
                                                                        mBluetoothHeadsetDevice);
                            } else if (mScoAudioMode == SCO_MODE_VR) {
                                        status = mBluetoothHeadset.stopVoiceRecognition(
                                                                      mBluetoothHeadsetDevice);
                            }

                            if (!status) {
                                mScoAudioState = SCO_STATE_INACTIVE;
                                broadcastScoConnectionState(
                                        AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                            }
                        } else if (getBluetoothHeadset()) {
                            mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
                        }
                    } else {
                        mScoAudioState = SCO_STATE_INACTIVE;
                        broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                    }
                }
            }
        }
    }

packages\apps\Bluetooth\src\com\android\bluetooth\hfp\HeadsetService.java下面的startScoUsingVirtualVoiceCall接口。
 

    public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
        if (DBG) log("startScoUsingVirtualVoiceCall()");
        if (mService != null && isEnabled() && isValidDevice(device)) {
            try {
                return mService.startScoUsingVirtualVoiceCall(device);
            } catch (RemoteException e) {
                Log.e(TAG, e.toString());
            }
        } else {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
        }
        return false;
    }

@packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetService.java

        public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
            HeadsetService service = getService();
            if (service == null) return false;
            return service.startScoUsingVirtualVoiceCall(device);
        }
    boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
        /* Do not ignore request if HSM state is still Disconnected or
           Pending, it will be processed when transitioned to Connected */
        mStateMachine.sendMessage(HeadsetStateMachine.VIRTUAL_CALL_START, device);
        return true;
    }

@packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java中处理:

    synchronized boolean initiateScoUsingVirtualVoiceCall() {
        if (DBG) log("initiateScoUsingVirtualVoiceCall: Received");
        // 1. Check if the SCO state is idle
        if (isInCall() || mVoiceRecognitionStarted) {
            Log.e(TAG, "initiateScoUsingVirtualVoiceCall: Call in progress.");
            return false;
        }

        // 2. Send virtual phone state changed to initialize SCO
        processCallState(new HeadsetCallState(0, 0,
            HeadsetHalConstants.CALL_STATE_DIALING, "", 0), true);
        processCallState(new HeadsetCallState(0, 0,
            HeadsetHalConstants.CALL_STATE_ALERTING, "", 0), true);
        processCallState(new HeadsetCallState(1, 0,
            HeadsetHalConstants.CALL_STATE_IDLE, "", 0), true);
        setVirtualCallInProgress(true);
        // Done
        if (DBG) log("initiateScoUsingVirtualVoiceCall: Done");
        return true;
    }

这个接口最后虚拟了拨号中,响铃,与接听操作。可以看到这三个操作是拨打电话时就一起调用的,因此对于微信app来说,它是在对方接听之后或者自己接听之后才调用的这个接口,实际上此时通话已经建立了。这是为什么这种通话车机端不会显示来电通知框。因为对于车机而言,是微信在通话建立后才调用startScoUsingVirtualVoiceCall来通知车机现在在打电话。

setBluetoothScoOn@AudioManager.java

  -> setBluetoothScoOnInt(on)@AudioService.java

    ->

  

@AudioService.java

public void setBluetoothScoOnInt(boolean on) {2508        if (on) {2509            mForcedUseForComm = AudioSystem.FORCE_BT_SCO;2510        } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {2511            mForcedUseForComm = AudioSystem.FORCE_NONE;2512        }25132514        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,2515                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);2516        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,2517                AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);2518    }

    public void handleMessage(Message msg) {4313            switch (msg.what) {

               case MSG_SET_FORCE_USE:4376                case MSG_SET_FORCE_BT_A2DP_USE:4377                    setForceUse(msg.arg1, msg.arg2);4378                    break;

4299        private void setForceUse(int usage, int config) {4300            synchronized (mConnectedDevices) {4301                setForceUseInt_SyncDevices(usage, config);4302            }4303        }

29    private void setForceUseInt_SyncDevices(int usage, int config) {5330        switch (usage) {5331            case AudioSystem.FOR_MEDIA:5332                if (config == AudioSystem.FORCE_NO_BT_A2DP) {5333                    mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ALL_A2DP;5334                } else { // config == AudioSystem.FORCE_NONE5335                    mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ALL_A2DP;5336                }5337                break;5338            case AudioSystem.FOR_DOCK:5339                if (config == AudioSystem.FORCE_ANALOG_DOCK) {5340                    mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;5341                } else { // config == AudioSystem.FORCE_NONE5342                    mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;5343                }5344                break;5345            default:5346                // usage doesn't affect the broadcast of ACTION_AUDIO_BECOMING_NOISY5347        }5348        AudioSystem.setForceUse(usage, config);5349    }

@frameworks/av/media/libmedia/AudioSystem.cpp

735status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)736{737    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();738    if (aps == 0) return PERMISSION_DENIED;739    return aps->setForceUse(usage, config);740}

@frameworks/av/media/libmedia/IAudioPolicyService.cpp

126    virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)127    {128        Parcel data, reply;129        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());130        data.writeInt32(static_cast <uint32_t>(usage));131        data.writeInt32(static_cast <uint32_t>(config));132        remote()->transact(SET_FORCE_USE, data, &reply);133        return static_cast <status_t> (reply.readInt32());134    }

813        case SET_FORCE_USE: {814            CHECK_INTERFACE(IAudioPolicyService, data, reply);815            audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>(816                    data.readInt32());817            audio_policy_forced_cfg_t config =818                    static_cast <audio_policy_forced_cfg_t>(data.readInt32());819            reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));820            return NO_ERROR;821        } break;

@hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp

void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值