赞
踩
-
- @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
->
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)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。