此文章主要解决三个问题
1.高德导航的时候打电话会出现混音问题。
2.蓝牙音乐在播放的时候导航界面语音播报蓝牙音乐会暂停,播报结束会恢复播放不能同时输出问题。
3.蓝牙音乐在播放的时候和导航界面的语音播报混音输出的时候会有蓝牙音乐非常频繁且非常短暂卡顿的问题。
涉及的路径:
packages/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
packages/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamingStateMachine.java
system/bt/btif/src/btif_avrcp_audio_track.cpp
一,关于蓝牙电话和导航混音的问题
原因在于导航界面的语音播报是持续的并且是连续的,而且每次导航音频的播报都会有音频焦点抢占和播放的动作。而在7.1蓝牙中,只是对蓝牙电话焦点进行了一次抢占,这样就导致了 导航播报的时候会再次抢占到点形成了混音的问题,需要做的就是在蓝牙电话拨出或者接听的时候将系统的焦点修改为
mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
的方式进行抢占关于Android 7.1 的patch
diff --git a/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
index 66e25c8..3968429 100755
--- a/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
+++ b/apps/Bluetooth/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
@@ -330,6 +330,24 @@ final class HeadsetClientStateMachine extends StateMachine {
if (state == c.getState()) {
return;
}
+
+ if (state == BluetoothHeadsetClientCall.CALL_STATE_TERMINATED) {
+ if (c.getState() == BluetoothHeadsetClientCall.CALL_STATE_WAITING) {
+ Log.d(TAG, "Reject waiting call");
+ } else if (getCall(BluetoothHeadsetClientCall.CALL_STATE_HELD) != null) {
+ Log.d(TAG, "Has held call");
+ } else {
+ if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d(TAG, "abandonAudioFocus ");
+ // abandon audio focus after the mode has been set back to normal
+ mAudioManager.abandonAudioFocusForCall();
+ }
+ }
+ }
+
c.setState(state);
sendCallChangedIntent(c);
Log.d(TAG, "Exit setCallState()");
@@ -902,6 +920,36 @@ final class HeadsetClientStateMachine extends StateMachine {
Log.d(TAG, "updateCallsDone new call id:" + entry.getValue().getId());
sendCallChangedIntent(entry.getValue());
}
+
+ if ((getCurrentState() == mAudioOn) && (entry.getValue().getState() == BluetoothHeadsetClientCall.CALL_STATE_ACTIVE)) {
+ Log.d(TAG, "mode is AudioOn");
+ int newAudioMode = AudioManager.MODE_IN_CALL;
+ int currMode = mAudioManager.getMode();
+ if (currMode != newAudioMode) {
+ // request audio focus before setting the new mode
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ Log.d(TAG, "setAudioMode Setting audio mode from "
+ + currMode + " to " + newAudioMode);
+ mAudioManager.setMode(newAudioMode);
+ Log.d(TAG,"hfp_enable=true");
+ Log.d(TAG,"mAudioWbs is " + mAudioWbs);
+ if (mAudioWbs) {
+ Log.d(TAG,"Setting sampling rate as 16000");
+ mAudioManager.setParameters("hfp_set_sampling_rate=16000");
+ }
+ else {
+ Log.d(TAG,"Setting sampling rate as 8000");
+ mAudioManager.setParameters("hfp_set_sampling_rate=8000");
+ }
+ mAudioManager.setParameters("hfp_enable=true");
+ }
+ } else {
+ Log.d(TAG, "mode is NOT AudioOn; Don't change audio mode.");
+ }
}
mCalls = mCallsUpdate;
@@ -2098,6 +2146,27 @@ final class HeadsetClientStateMachine extends StateMachine {
// Ringing is not handled at this indication and rather should be
// implemented (by the client of this service). Use the
// CALL_STATE_INCOMING (and similar) handle ringing.
+
+ int newAudioMode = AudioManager.MODE_RINGTONE;
+ int currMode = mAudioManager.getMode();
+ if (currMode != newAudioMode) {
+ /// M: PTS TC_HF_ICA_BV_05_I {@
+ if ((currMode == AudioManager.MODE_IN_CALL) &&
+ (mInBandRingtone == HeadsetClientHalConstants.IN_BAND_RING_NOT_PROVIDED)) {
+ disconnectAudioNative(getByteAddress(mCurrentDevice));
+ mAudioManager.abandonAudioFocusForCall();
+ }
+ /// @}
+ // request audio focus before setting the new mode
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ Log.d(TAG, "setAudioMode Setting audio mode from "
+ + currMode + " to " + newAudioMode);
+ mAudioManager.setMode(newAudioMode);
+ }
+
break;
case EVENT_TYPE_CGMI:
Log.d(TAG, "cgmi:" + event.valueString);
@@ -2149,6 +2218,18 @@ final class HeadsetClientStateMachine extends StateMachine {
case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED:
Log.d(TAG, "Connected disconnects.");
// AG disconnects
+
+ if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d(TAG, "abandonAudioFocus");
+ // abandon audio focus after the mode has been set back to normal
+ mAudioManager.abandonAudioFocusForCall();
+ }
+ Log.d(TAG,"hfp_enable=false");
+ mAudioManager.setParameters("hfp_enable=false");
+
if (mCurrentDevice.equals(device)) {
broadcastConnectionState(mCurrentDevice,
BluetoothProfile.STATE_DISCONNECTED,
@@ -2196,6 +2277,11 @@ final class HeadsetClientStateMachine extends StateMachine {
// We need to set the volume after switching into HFP mode as some Audio HALs
// reset the volume to a known-default on mode switch.
+
+ /*
final int amVol =
mAudioManager.getStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO);
final int hfVol = amToHfVol(amVol);
@@ -2213,6 +2299,41 @@ final class HeadsetClientStateMachine extends StateMachine {
Log.d(TAG, "hf_volume " + hfVol);
mAudioManager.setParameters("hfp_enable=true");
mAudioManager.setParameters("hfp_volume=" + hfVol);
+ */
+ //New code
+ BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
+ if (mInBandRingtone == HeadsetClientHalConstants.IN_BAND_RING_PROVIDED && c != null) {
+ // Purpose: To workaroud audio driver limitation
+ Log.d(TAG, "Skip In-Band ringtone");
+ } else {
+ int newAudioMode = AudioManager.MODE_IN_CALL;
+ int currMode = mAudioManager.getMode();
+ if (currMode != newAudioMode) {
+ // request audio focus before setting the new mode
+ mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ Log.d(TAG, "setAudioMode Setting audio mode from "
+ + currMode + " to " + newAudioMode);
+ mAudioManager.setMode(newAudioMode);
+ }
+ Log.d(TAG,"hfp_enable=true");
+ Log.d(TAG,"mAudioWbs is " + mAudioWbs);
+ if (mAudioWbs) {
+ Log.d(TAG,"Setting sampling rate as 16000");
+ mAudioManager.setParameters("hfp_set_sampling_rate=16000");
+ }
+ else {
+ Log.d(TAG,"Setting sampling rate as 8000");
+ mAudioManager.setParameters("hfp_set_sampling_rate=8000");
+ }
+ mAudioManager.setParameters("hfp_enable=true");
+ }
+ broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_CONNECTED,
+ BluetoothHeadsetClient.STATE_AUDIO_CONNECTING);
+
+
transitionTo(mAudioOn);
break;
case HeadsetClientHalConstants.AUDIO_STATE_CONNECTING:
@@ -2339,6 +2460,18 @@ final class HeadsetClientStateMachine extends StateMachine {
if (mCurrentDevice.equals(device)) {
processAudioEvent(HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED,
device);
+
+ if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d(TAG, "abandonAudioFocus");
+ // abandon audio focus after the mode has been set back to normal
+ mAudioManager.abandonAudioFocusForCall();
+ }
+ Log.d(TAG,"hfp_enable=false");
+ mAudioManager.setParameters("hfp_enable=false");
broadcastConnectionState(mCurrentDevice,
BluetoothProfile.STATE_DISCONNECTED,
BluetoothProfile.STATE_CONNECTED);
@@ -2371,6 +2504,20 @@ final class HeadsetClientStateMachine extends StateMachine {
// (such as Telecom) and hence this will still keep the call around, there
// is not much we can do here since dropping the call without user consent
// even if the audio connection snapped may not be a good idea.
+ BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
+ if (c==null) {
+ if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d(TAG, "abandonAudioFocus");
+ // abandon audio focus after the mode has been set back to normal
+ mAudioManager.abandonAudioFocusForCall();
+ }
+ }
Log.d(TAG,"hfp_enable=false");
mAudioManager.setParameters("hfp_enable=false");
broadcastAudioState(device,
二,关于蓝牙音乐和导航语音播报的时候不能混音输出的问题。
原因是航界面的语音播报是持续的并且是连续的,而7.1的蓝牙在收到焦点切换的时候会进行蓝牙音乐的释放与焦点转换,这个问题的处理方式是对音频焦点切换的时候不做处理,让蓝牙音乐继续之前的播放,这样就可以在蓝牙音乐播放的同事,导航的音频也可以持续的输出,形成混音同时输出
patch如下:
diff --git a/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamingStateMachine.java b/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamingStateMachine.java
index b8b11d1..4c36729 100644
--- a/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamingStateMachine.java
+++ b/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamingStateMachine.java
@@ -365,7 +365,8 @@ final class A2dpSinkStreamingStateMachine extends StateMachine {
if (newAudioFocus == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
- sendAvrcpPause();
//sendAvrcpPause();
- transitionTo(mFTransient);
+ //transitionTo(mFTransient);
}
if (newAudioFocus == AudioManager.AUDIOFOCUS_LOSS) {
sendAvrcpPause();
@@ -417,7 +418,8 @@ final class A2dpSinkStreamingStateMachine extends StateMachine {
if (newAudioFocus == AudioManager.AUDIOFOCUS_GAIN)
- sendAvrcpPlay();
//sendAvrcpPlay();
- transitionTo(mFGranted);
+ //transitionTo(mFGranted);
if (newAudioFocus == AudioManager.AUDIOFOCUS_LOSS) {
abandonAudioFocus();
三,蓝牙音乐和导航播报连续短暂卡顿问题
这个问题是属于蓝牙音乐和导航播报走的是不同的音频流,音频流流频繁切换导致方法是使用别的音频流通道
diff --git a/bt/btif/src/btif_avrcp_audio_track.cpp b/bt/btif/src/btif_avrcp_audio_track.cpp
index 89d2a5f..6e6377e 100644
--- a/bt/btif/src/btif_avrcp_audio_track.cpp
+++ b/bt/btif/src/btif_avrcp_audio_track.cpp
@@ -43,7 +43,7 @@
sp<android::AudioTrack> track =
new android::AudioTrack(AUDIO_STREAM_MUSIC, trackFreq, AUDIO_FORMAT_PCM_16_BIT,
channelType, (size_t) 0 /*frameCount*/,
- (audio_output_flags_t)AUDIO_OUTPUT_FLAG_FAST,
+ (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER,
NULL /*callback_t*/, NULL /*void* user*/, 0 /*notificationFrames*/,
AUDIO_SESSION_ALLOCATE, android::AudioTrack::TRANSFER_SYNC);
assert(track != NULL);