Android應(yīng)用打斷后的藍牙外放問題分析

背景

幾年前移必,藍牙外放問題一直是業(yè)務(wù)的痛點,工單多毡鉴,原因雜崔泵,檢測難,分析慢猪瞬,經(jīng)過幾個版本的需求迭代后憎瘸,工單數(shù)下降超過了95%。

可是最近又有客戶反饋撑螺,在藍牙場景音頻通話過程中含思,被其他通話應(yīng)用打斷,就會出現(xiàn)藍牙外放問題甘晤。本篇用來分析該問題的原因和解決方法含潘。

分析過程

首先介紹下藍牙外放的本質(zhì)。對于Android應(yīng)用线婚,在通話音量下遏弱,應(yīng)用必須主動建立sco鏈接,這時候應(yīng)用才可以使用藍牙耳機進行采集和播放塞弊,如果不主動建立sco鏈接漱逸,那么采播通道就不會走藍牙,此時就出現(xiàn)了藍牙外放問題游沿∈问悖可是并不是應(yīng)用建立sco鏈接就一定會成功,Android內(nèi)部會針對通話音量的mode owner進行檢查诀黍, 如果當前應(yīng)用并不是mode owner袋坑,那么也會鏈接sco失敗。那么這時候就可以得到一個結(jié)論眯勾,出現(xiàn)藍牙外放問題枣宫,主要是如下2個原因:

  • 應(yīng)用未建立sco鏈接
  • 應(yīng)用建立sco鏈接失敗了

那接下來分析思路就清晰了,出現(xiàn)藍牙外放吃环,就從如上兩點進行排查即可也颤。

這時候需要先看audioservice的dump信息,對應(yīng)的命令是

adb shell dumpsys audio > audio.txt

截取時間點log如下:

02-22 19:24:32:036 setMode(MODE_IN_COMMUNICATION) from package=com.tencent.liteav.demo pid=24442 selected mode=MODE_IN_COMMUNICATION by pid=24442
02-22 19:24:43:714 setMode(MODE_IN_COMMUNICATION) from package=com.tencent.mobileqq pid=25280 selected mode=MODE_IN_COMMUNICATION by pid=25280
02-22 19:24:48:765 setMode(MODE_NORMAL) from package=com.tencent.mobileqq pid=25280 selected mode=MODE_IN_COMMUNICATION by pid=24442
02-22 19:24:49:292 setMode(MODE_IN_COMMUNICATION) from package=com.tencent.mobileqq pid=25280 selected mode=MODE_IN_COMMUNICATION by pid=25280
02-22 19:24:55:335 setMode(MODE_NORMAL) from package=MSG_CHECK_MODE_FOR_UID pid=25280 selected mode=MODE_IN_COMMUNICATION by pid=24442
02-22 19:24:55:369 mode IN COMMUNICATION timeout for package=com.tencent.mobileqq pid=25280
02-22 19:25:04:586 setMode(MODE_NORMAL) from package=com.tencent.liteav.demo pid=24442 selected mode=MODE_NORMAL by pid=0

外放時間點是 19:24:49 到 19:25:04郁轻。

對應(yīng)的sco 鏈接軌跡如下:

02-22 19:24:32:058 startBluetoothSco()) from u/pid:11823/24442
02-22 19:24:41:264 startBluetoothSco()) from u/pid:10424/25280
02-22 19:24:48:761 stopBluetoothSco()) from u/pid:10424/25280
02-22 19:24:49:863 startBluetoothSco()) from u/pid:11823/24442
02-22 19:24:53:868 stopBluetoothSco()) from u/pid:11823/24442
02-22 19:24:57:877 startBluetoothSco()) from u/pid:11823/24442
02-22 19:25:01:883 stopBluetoothSco()) from u/pid:11823/24442

從log可以推斷問題軌跡如下:

  1. com.tencent.liteav.demo 先使用通話音量, 同時建立sco鏈接
  2. com.tencent.mobileqq 接入翅娶,也就是收到了 QQ語音電話,同時QQ也建立sco鏈接
  3. com.tencent.mobileqq 退出,也就是QQ語音電話掛掉故觅,同時QQ也結(jié)束sco鏈接
  4. com.tencent.liteav.demo 開始建立sco厂庇,然后停止sco進行循環(huán)

demo 只有在建立sco后,未收到sco鏈接成功事件才會嘗試重新鏈接sco输吏,那就可以得出如下結(jié)論:

  • 應(yīng)用在通話音量下有進行sco鏈接
  • 應(yīng)用鏈接sco失敗了

那接下來就需要看為什么sco鏈接失敗了权旷,這時候就可以參考下logcat日志,和正常case對比下就可以獲取到差異信息贯溅,先看鏈接sco正常時候的log:

02-22 19:24:32.058 24442 25180 I AudioManager: startBluetoothSco() packageName = com.tencent.liteav.demo
02-22 19:24:32.058 24442 25180 I AudioManager: In startbluetoothSco(), calling application: com.tencent.liteav.demo
02-22 19:24:32.058  1184  8982 I AS.AudioService: In startBluetoothSco()
02-22 19:24:32.058   971  2570 D APM_AudioPolicyManager: setStreamVolumeIndex: stream AUDIO_STREAM_DTMF index: 10 attributes={ Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags:  }
02-22 19:24:32.058   971  2570 D APM_AudioPolicyManager: setVolumeIndexForAttributes: group 4 matching with { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags:  }
02-22 19:24:32.058   971  2570 D APM_AudioPolicyManager: setVolumeCurveIndex device 00000004, index 10
02-22 19:24:32.058  1184  8982 I AS.AudioService: In startBluetoothScoInt(), scoAudioMode: -1
02-22 19:24:32.058  1184  8982 I AS.AudioDeviceBroker: In setSpeakerphoneOffForPid: 24442
02-22 19:24:32.058  1184  8982 I AS.AudioDeviceBroker: In updateSpeakerphoneOn(), mForcedUseForCommExt: 0
02-22 19:24:32.058  1184  8982 I AS.BtHelper: In requestScoState(), state: 12, scoAudioMode: -1
02-22 19:24:32.058   971   971 D AudioPolicyManagerCustom: setForceUse() usage 0, config 0, mPhoneState 3
02-22 19:24:32.059   971  2570 D APM_AudioPolicyManager: setStreamVolumeIndex: stream AUDIO_STREAM_DTMF index: 15 attributes={ Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags:  }
02-22 19:24:32.059   971  2570 D APM_AudioPolicyManager: setVolumeIndexForAttributes: group 4 matching with { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags:  }

對比異常時候的log如下:

02-22 19:24:57.874 24442 25180 I AudioManager: startBluetoothSco() packageName = com.tencent.liteav.demo
02-22 19:24:57.874 24442 25180 I AudioManager: In startbluetoothSco(), calling application: com.tencent.liteav.demo
02-22 19:24:57.874  1184  1240 I AS.AudioService: In startBluetoothSco()
02-22 19:24:57.876  1184  1240 I AS.AudioService: In startBluetoothScoInt(), scoAudioMode: -1
02-22 19:24:57.876  1184  1240 I AS.AudioDeviceBroker: In setSpeakerphoneOffForPid: 24442
02-22 19:24:57.876  1184  1240 I AS.AudioDeviceBroker: In updateSpeakerphoneOn(), mForcedUseForCommExt: 0
02-22 19:24:57.877  1184  1240 I AS.BtHelper: In requestScoState(), state: 12, scoAudioMode: -1
02-22 19:24:57.877   971  5575 D AudioPolicyManagerCustom: setForceUse() usage 0, config 0, mPhoneState 3
02-22 19:24:57.878  4819  5438 E HeadsetStateMachine: returning mCurrentState as Connected
02-22 19:24:57.879  1184  1240 I AS.BtHelper: In checkScoAudioState(), mScoAudioState: 0
02-22 19:24:57.879  1184  1240 W AS.BtHelper: requestScoState: audio mode is not NORMAL and modeOwnerPid 25280 != creatorPid 24442

可以看到有個關(guān)鍵信息:
!!#ff0000 02-22 19:24:57.879 1184 1240 W AS.BtHelper: requestScoState: audio mode is not NORMAL and modeOwnerPid 25280 != creatorPid 24442
!!

bthelper 報錯了拄氯,提示當前應(yīng)用非mode owner,那原因就清楚了它浅,由于當前應(yīng)用并不是modeowner译柏,所以鏈接sco不會成功

從時間點上看姐霍,19:24:57 時QQ電話已經(jīng)打斷結(jié)束了鄙麦, 音量類型也被刷新成demo了,這時候mode owner 也應(yīng)該要更新為demo:

02-22 19:24:55:335 setMode(MODE_NORMAL) from package=MSG_CHECK_MODE_FOR_UID pid=25280 selected mode=MODE_IN_COMMUNICATION by pid=24442

可是19:24:57 時候mode owner 還是qq镊折,因此可以判斷出是系統(tǒng)bug胯府。

那應(yīng)用如何解決呢?
其實知道原因后恨胚,解決辦法就比較順理成章了骂因,應(yīng)用只需要在建立sco前嘗試爭取成mode owner 就可以了,也就是設(shè)置通話音量類型赃泡。
按照這樣修改后寒波,客戶反饋藍牙外放問題得到了修復(fù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末升熊,一起剝皮案震驚了整個濱河市俄烁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌级野,老刑警劉巖页屠,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異勺阐,居然都是意外死亡,警方通過查閱死者的電腦和手機矛双,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門渊抽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人议忽,你說我怎么就攤上這事懒闷。” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵愤估,是天一觀的道長帮辟。 經(jīng)常有香客問我,道長玩焰,這世上最難降的妖魔是什么由驹? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮昔园,結(jié)果婚禮上蔓榄,老公的妹妹穿的比我還像新娘。我一直安慰自己默刚,他們只是感情好甥郑,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著荤西,像睡著了一般澜搅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上邪锌,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天勉躺,我揣著相機與錄音,去河邊找鬼秃流。 笑死赂蕴,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的舶胀。 我是一名探鬼主播概说,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嚣伐!你這毒婦竟也來了糖赔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤轩端,失蹤者是張志新(化名)和其女友劉穎放典,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體基茵,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡奋构,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拱层。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弥臼。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖根灯,靈堂內(nèi)的尸體忽然破棺而出径缅,到底是詐尸還是另有隱情掺栅,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布纳猪,位于F島的核電站氧卧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏氏堤。R本人自食惡果不足惜沙绝,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丽猬。 院中可真熱鬧宿饱,春花似錦、人聲如沸脚祟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽由桌。三九已至为黎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間行您,已是汗流浹背铭乾。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留娃循,地道東北人炕檩。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像捌斧,于是被迫代替她去往敵國和親笛质。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容