安卓源碼避坑指南3——撥打電話的SIM卡無效導致藍牙斷開連接

安卓源碼避坑指南3——撥打電話的SIM卡無效導致藍牙斷連

在這裏插入圖片描述

它來了、它來了,它帶着BUG趕來了,歡迎大家查看本期的安卓源碼避坑指南。本期的問題場景比較特殊,電話SIM卡是無效的(欠費過期了,很是貧窮…)。

開開心心地上着班、摸着魚(-_-),突然工作郵件提醒,一經查看原來是QA同學甩過來個問題。那咱就話不多說,先簡單介紹下本篇的問題場景。

測試環境:Android 9的車機系統 + 手機中的SIM卡爲無效SIM卡

測試步驟

  1. 車機和手機使用藍牙相互連接成功
  2. 車機端主動撥打電話

測試現象:由於手機中SIM卡爲無效電話卡所以電話撥打失敗,但是幾秒鐘過後手機與車機間的藍牙連接斷開

當看到這麼個場景+問題現象後,我是懵逼的。打個電話藍牙連接就斷開,這麼牛逼的嗎?經過分析logcat發現藍牙服務進程號有改變,那問題原因指向就很明顯了:

  • 用戶主動開關藍牙
  • 藍牙服務crash

由於測試步驟中不涉及開關藍牙操作,那肯定就是藍牙服務進程crash。根據這個基本判斷提取相關crash-log做進一步分析。

Process: com.android.bluetooth
PID: 21997
Flags: 0x30c8be45
Package: com.android.bluetooth v28 (9)
Foreground: No
Build:系統版本號(此處省略。。。)

java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED flg=0x10000010 (has extras) } in com.android.bluetooth.hfpclient.connserv.HfpClientConnectionService$1@72e6f2
	at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1401)
	at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
	at android.os.Handler.handleCallback(Handler.java:873)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:193)
	at android.app.ActivityThread.main(ActivityThread.java:6718)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.bluetooth.BluetoothHeadsetClientCall.getNumber()' on a null object reference
	at com.android.bluetooth.hfpclient.connserv.HfpClientConnection.finishInitializing(HfpClientConnection.java:92)
	at com.android.bluetooth.hfpclient.connserv.HfpClientConnection.<init>(HfpClientConnection.java:61)
	at com.android.bluetooth.hfpclient.connserv.HfpClientDeviceBlock.buildConnection(HfpClientDeviceBlock.java:253)
	at com.android.bluetooth.hfpclient.connserv.HfpClientDeviceBlock.handleCall(HfpClientDeviceBlock.java:169)
	at com.android.bluetooth.hfpclient.connserv.HfpClientConnectionService$1.onReceive(HfpClientConnectionService.java:122)
	at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1391)
	... 8 more

從以上問題log明顯看到程序運行過程中遇到空指針調用從而引發com.android.bluetooth進程crash,導致藍牙連接斷開的問題根因crash找到了,那是怎麼觸發這個crash的呢?我們試着從源碼分析下這塊的流程。

首先查看snoop文件,由於問題產生時只有撥打電話的操作,所以分析下AT命令的交互:
在這裏插入圖片描述

從HCI上可以看出AT交互很簡單,就是一條ATD指令請求撥打電話,由於手機SIM卡無效,10s手機回覆了錯誤的AT命令。10s的時間設定是因爲手機藍牙服務HeadsetService. dialOutgoingCall( )在收到AT撥打電話指令後會給電話模塊發送對應的廣播並設置定時器:
在這裏插入圖片描述

手機端撥打電話10s超時後發送AT_RESPONSE_ERROR回覆車機藍牙,那車機收到這條錯誤指令後是怎麼處理才導致crash了呢?咱就跟着程序分析下去,處理的時序圖如下:
在這裏插入圖片描述
由於這個特殊場景使得HfpClientConnectionService對於這次撥打電話的操作而言第一次接收到的ACTION_CALL_CHANGED中call.state就是CALL_STATE_TERMINATED,從而初始化HfpClientConnection時調用了close()將mCurrentCall又置爲空值,這樣才遇到mCurrentCall.getNumber()對空指針取值引發crash。

分析到這裏我們都知道mCurrentCall的值爲空的原因了,那對應的解決方案就請大家集思廣益在評論區一起交流討論吧!

經過這樣類似問題的回溯,我不禁對QA測試工程師越發佩服,因爲使用的手機中SIM卡是無效卡的情況幾乎不可能遇到,那對於本期分析的問題就很難被發現。正是QA們天馬行空的魔鬼操作才讓這些問題提前暴露出來,讓藍牙系統整體上更穩定,給測試大佬們敬茶 -_-。

本期是安卓源碼避坑指南系列的第三篇文章了,想了解更多安卓源碼bug的同學可以翻看以前的文章,也歡迎感興趣的小夥伴私信留言共同學習。

更多互聯互通技術,歡迎關注微信公衆號:Connectivity
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章