安卓原始碼避坑指南6——**記錄為空號觸發藍芽重啟
對於空的**記錄想必大家都會感到很奇怪,今天就給大家分享個空**記錄引起藍芽crash的原生問題。
觸發藍芽重啟指的是pbap協議pce端的藍芽程序crash,從而引發藍芽自動重啟的問題。追蹤分析後問題根因主要在calllogpullrequest.updatetimescontacted()中,該方法用來統計聯絡歷史中相同聯絡人的通話次數,並同步到通訊錄資料庫中。
updatetimescontacted()是從android-9才新增的方法,因此在android-8及以下版本上不存在此問題,只在android-9及以上版本上存在。
那空**記錄是如何一步步觸發藍芽重啟了呢?話不多說,直接上同步的聯絡歷史資料解析流程。
pce端的藍芽協議棧接收到聯絡歷史資料:
接收到的聯絡歷史vcard中的**號碼資訊在hci層顯示異常,其實該條聯絡歷史就是我們這篇文章中所要討論的空的聯絡歷史。手機端(pse)在組裝聯絡歷史資料時通過藍芽傳送到請求方,由於該號碼不存在,因此會將字串「未知號碼」或「無號碼」等通過 utf-8編碼 格式轉換成相應資料傳送給pce。
上圖中pce端接收到的**號碼資料為:0xe69caae79fa5e58fb7e7a081
經utf-8編碼轉換成對應字串為:未知號碼
資料再經過vcardentry.addphone()新增**號碼時,會依次提取char型字元判斷該字元是否符合標準,由於是「未知號碼」字串轉換的資料,顯而易見builder最後是個空字串,因此最後新增的**號碼資料是個空值。
聯絡歷史資料全部解析完成後,藍芽程序通過calllogpullrequest.onpullcomplete()將聯絡歷史寫入資料庫中,並統計每個**號碼的通話次數。寫資料庫完成後判斷最後一條聯絡歷史的型別如果是outgoing_type(呼出型別),則更新通訊錄中的聯絡次數。(這塊的判斷通話型別邏輯感覺沒必要
以上條件滿足,則在更新聯絡次數的方法 updatetimescontacted() 中使用乙個空的**號碼查詢資料庫,觸發illegalargumentexception引數錯誤,引發藍芽程序crash。
問題根因分析到這兒就很清楚了,那在android-9及以上版本的原始碼中規避此類問題的解決方案就小菜一碟,只需要在更新聯絡次數的for迴圈中首先對key值(對應於**號碼)新增判空處理即可。
更新最後一條記錄
修改最後一條記錄 update userinfo set userid 55 where 1 order by userid desc limit 1 刪除第一條記錄 delete from userinfo where 1 order by userid limit 1 mysql 總結 在寫這段...
判斷第一條或最後一條記錄
標籤具有以下一些屬性 var 迭代引數的名稱。在迭代體中可以使用的變數的名稱,用來表示每乙個迭代變數。型別為string。items 要進行迭代的集合。對於它所支援的型別將在下面進行講解。varstatus 迭代變數的名稱,用來表示迭代的狀態,可以訪問到迭代自身的資訊。begin 如果指定了item...
SQL Server 如何查詢最後一條記錄
在機房收費系統的資料庫中,有這樣的乙個表 worklog info 這個表有什麼作用呢?這個表的作用就是記錄著工作人員的操作記錄,也就是說,乙個一般使用者 操作員或管理員 登陸這個系統,和正常關閉這個系統以後,在這個表中就會增加一條該使用者的使用記錄!下面是該錶的各個欄位名,有的同學就感覺其中ser...