当前位置:   article > 正文

startBluetoothSco和setBluetoothScoOn流程

startbluetoothsco
 
  1. @frameworks/base/media/java/android/media/AudioManager.java
  2. public void startBluetoothSco(){
  3. IAudioService service = getService();
  4. try {
  5. service.startBluetoothSco(mICallBack,
  6. getContext().getApplicationInfo().targetSdkVersion);
  7. } catch (RemoteException e) {
  8. Log.e(TAG, "Dead object in startBluetoothSco", e);
  9. }
  10. }
  11. startBluetoothSco@frameworks/base/services/core/java/com/android/server/audio/AudioService.java
  12. /** @see AudioManager#startBluetoothSco() */
  13. public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
  14. int scoAudioMode =
  15. (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
  16. SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
  17. startBluetoothScoInt(cb, scoAudioMode);
  18. }
  19. @frameworks/base/services/core/java/com/android/server/audio/AudioService.java
  20. void startBluetoothScoInt(IBinder cb, int scoAudioMode){
  21. if (!checkAudioSettingsPermission("startBluetoothSco()") ||
  22. !mSystemReady) {
  23. return;
  24. }
  25. ScoClient client = getScoClient(cb, true);
  26. // The calling identity must be cleared before calling ScoClient.incCount().
  27. // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
  28. // and this must be done on behalf of system server to make sure permissions are granted.
  29. // The caller identity must be cleared after getScoClient() because it is needed if a new
  30. // client is created.
  31. final long ident = Binder.clearCallingIdentity();
  32. client.incCount(scoAudioMode);
  33. Binder.restoreCallingIdentity(ident);
  34. }
  35. @frameworks/base/services/core/java/com/android/server/audio/AudioService.java
  36. public void incCount(int scoAudioMode) {
  37. synchronized(mScoClients) {
  38. requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
  39. if (mStartcount == 0) {
  40. try {
  41. mCb.linkToDeath(this, 0);
  42. } catch (RemoteException e) {
  43. // client has already died!
  44. Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death");
  45. }
  46. }
  47. mStartcount++;
  48. }
  49. }
  1. private void requestScoState(int state, int scoAudioMode) {
  2. checkScoAudioState();
  3. if (totalCount() == 0) {
  4. if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
  5. // Make sure that the state transitions to CONNECTING even if we cannot initiate
  6. // the connection.
  7. broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
  8. // Accept SCO audio activation only in NORMAL audio mode or if the mode is
  9. // currently controlled by the same client process.
  10. synchronized(mSetModeDeathHandlers) {
  11. if ((mSetModeDeathHandlers.isEmpty() ||
  12. mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
  13. (mScoAudioState == SCO_STATE_INACTIVE ||
  14. mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
  15. if (mScoAudioState == SCO_STATE_INACTIVE) {
  16. mScoAudioMode = scoAudioMode;
  17. if (scoAudioMode == SCO_MODE_UNDEFINED) {
  18. if (mBluetoothHeadsetDevice != null) {
  19. mScoAudioMode = new Integer(Settings.Global.getInt(
  20. mContentResolver,
  21. "bluetooth_sco_channel_"+
  22. mBluetoothHeadsetDevice.getAddress(),
  23. SCO_MODE_VIRTUAL_CALL));
  24. if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
  25. mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
  26. }
  27. } else {
  28. mScoAudioMode = SCO_MODE_RAW;
  29. }
  30. }
  31. if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
  32. boolean status = false;
  33. if (mScoAudioMode == SCO_MODE_RAW) {
  34. status = mBluetoothHeadset.connectAudio();
  35. } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
  36. status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
  37. mBluetoothHeadsetDevice);
  38. } else if (mScoAudioMode == SCO_MODE_VR) {
  39. status = mBluetoothHeadset.startVoiceRecognition(
  40. mBluetoothHeadsetDevice);
  41. }
  42. if (status) {
  43. mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
  44. } else {
  45. broadcastScoConnectionState(
  46. AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
  47. }
  48. } else if (getBluetoothHeadset()) {
  49. mScoAudioState = SCO_STATE_ACTIVATE_REQ;
  50. }
  51. } else {
  52. mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
  53. broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
  54. }
  55. } else {
  56. broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
  57. }
  58. }
  59. } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
  60. (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
  61. mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
  62. if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
  63. if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
  64. boolean status = false;
  65. if (mScoAudioMode == SCO_MODE_RAW) {
  66. status = mBluetoothHeadset.disconnectAudio();
  67. } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
  68. status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
  69. mBluetoothHeadsetDevice);
  70. } else if (mScoAudioMode == SCO_MODE_VR) {
  71. status = mBluetoothHeadset.stopVoiceRecognition(
  72. mBluetoothHeadsetDevice);
  73. }
  74. if (!status) {
  75. mScoAudioState = SCO_STATE_INACTIVE;
  76. broadcastScoConnectionState(
  77. AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
  78. }
  79. } else if (getBluetoothHeadset()) {
  80. mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
  81. }
  82. } else {
  83. mScoAudioState = SCO_STATE_INACTIVE;
  84. broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
  85. }
  86. }
  87. }
  88. }
  89. }

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

  1. public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
  2. if (DBG) log("startScoUsingVirtualVoiceCall()");
  3. if (mService != null && isEnabled() && isValidDevice(device)) {
  4. try {
  5. return mService.startScoUsingVirtualVoiceCall(device);
  6. } catch (RemoteException e) {
  7. Log.e(TAG, e.toString());
  8. }
  9. } else {
  10. Log.w(TAG, "Proxy not attached to service");
  11. if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
  12. }
  13. return false;
  14. }

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

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

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

  1. synchronized boolean initiateScoUsingVirtualVoiceCall() {
  2. if (DBG) log("initiateScoUsingVirtualVoiceCall: Received");
  3. // 1. Check if the SCO state is idle
  4. if (isInCall() || mVoiceRecognitionStarted) {
  5. Log.e(TAG, "initiateScoUsingVirtualVoiceCall: Call in progress.");
  6. return false;
  7. }
  8. // 2. Send virtual phone state changed to initialize SCO
  9. processCallState(new HeadsetCallState(0, 0,
  10. HeadsetHalConstants.CALL_STATE_DIALING, "", 0), true);
  11. processCallState(new HeadsetCallState(0, 0,
  12. HeadsetHalConstants.CALL_STATE_ALERTING, "", 0), true);
  13. processCallState(new HeadsetCallState(1, 0,
  14. HeadsetHalConstants.CALL_STATE_IDLE, "", 0), true);
  15. setVirtualCallInProgress(true);
  16. // Done
  17. if (DBG) log("initiateScoUsingVirtualVoiceCall: Done");
  18. return true;
  19. }

这个接口最后虚拟了拨号中,响铃,与接听操作。可以看到这三个操作是拨打电话时就一起调用的,因此对于微信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)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号