1. QQ calls, WeChat calls, phone calls, when the ringtone is remembered, why does the ringtone only ring on the mobile phone? And the bluetooth headset only beeps?
(1) Call ringtone playback
streamType = 2(AUDIO_STREAM_RING)
APM::AudioPolicyManager: startOutput() output 18, stream 2, session 24
(2) Engine::getStrategyForStream() function can get stream 2 corresponding to
strategy 2 (STRATEGY_SONIFICATION)
(3) Select device
APM::AudioPolicyEngine: getDeviceForStrategy() strategy 2, device 82
结果为AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | AUDIO_DEVICE_OUT_SPEAKER
This place is strange, the selected devices are bluetooth devices and speakers, why only the speakers have ringtones?
It can be found in the log that
bt_a2dp_hw: out_set_parameters: state 5
5 corresponds to AUDIO_A2DP_STATE_STANDBY
After a lot of searching, it can be found that
it runs when the bell rings
adb shell dumpsys media.audio_flinger results
For Bluetooth devices:
Output thread 0xecec0000 type 0 (MIXER):
Thread name: AudioOut_441
I/O handle: 1089
TID: 2033
Standby: yes
Sample rate: 44100 Hz
HAL frame count: 2560
HAL format: 0x1 (pcm16)
HAL buffer size: 10240 bytes
Channel count: 2
Channel mask: 0x00000003 (front-left, front-right)
Format: 0x1 (pcm16)
Frame size: 4 bytes
Pending config events: none
Output device: 0x80 (BLUETOOTH_A2DP)
Tips
When there are multiple output devices, each device corresponds to a Mixthread, and then corresponds to a total DuplicatingThread.
The Output thread corresponding to the Bluetooth device is in the Standby state when the ringtone is playing. And this state assignment is easy to find (Threads.cpp):
if ((!mActiveTracks.size() && systemTime() > mStandbyTimeNs) ||
isSuspended()) {
// put audio hardware into standby after short delay
if (shouldStandby_l()) {
threadLoop_standby();
mStandby = true;
}
After some searching, the truth came out:
AudioPolicyManager setPhoneState will call the checkA2dpSuspend() function, which eventually leads to Bluetooth Thread standBy. Then the entire Bluetooth output-related MixThread is suspended. At this time, the out_write function will definitely not be called to write down the ringtone data, and no sound will be emitted. .
Look at the official and see the comment in the checkA2dpSuspend function:
// suspend A2DP output if:
// (NOT already suspended) &&
// ((SCO device is connected &&
// (forced usage for communication || for record is SCO))) ||
// (phone state is ringing || in call)//响铃的时候要把a2dp挂起,注意是a2dp
//
// restore A2DP output if:
// (Already suspended) &&
// ((SCO device is NOT connected ||
// (forced usage NOT for communication && NOT for record is SCO))) &&
// (phone state is NOT ringing && NOT in call)
//
Based on the English level of the lower level 4, the general idea is: when making a call or is ringing (after setPhonestate 0) (sco must be connected successfully), use sco and suspend a2dp.
The difference between Baidu Soso sco and a2dp:
Bluetooth generally has two voice-related modes: A2DP and SCO. The former is for high-quality music playback (commonly known as: only in and out), and the latter is for voice calls (commonly known as: in and out).
Excerpted from: http://blog.csdn.net/kangear/article/details/38780185 (If there is any offense, please forgive me)
2. During a call, if the handsfree is turned on, the sound is no longer output from the Bluetooth device, but from the mobile phone. Why?
Let's take a look.
After the call is connected, the phone application will normally call
setBluetoothScoOn() to switch the Bluetooth device to Sco mode.
public void setBluetoothScoOnInt(boolean on) {
if (on) {
//通话时强制使用BT_SCO
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
} else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
mForcedUseForComm = AudioSystem.FORCE_NONE;
}
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
}
, after clicking "Speaker" setSpeakerphoneOn()
public void setSpeakerphoneOn(boolean on){
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
return;
}
if (on) {
if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
//如果之前设置了通话强制使用BT_SCO
//先取消强制使用(FORCE_NONE)
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);
}
//设置强制使用SPEAKER
mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
} else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
mForcedUseForComm = AudioSystem.FORCE_NONE;
}
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
}
case MSG_SET_FORCE_USE:
case MSG_SET_FORCE_BT_A2DP_USE:
setForceUse(msg.arg1, msg.arg2);
break;
//往下,AudioPolicyManager setForceUse的调用就略过不提了。
so. . . At once. . . not much to say