平臺(tái):
Rockchip 3399
Android 8.1
問題:
開機(jī)后慢宗,內(nèi)置/sdcard分區(qū)不可訪問,無法掛載伊脓,/storage/xxxx對(duì)應(yīng)得是外置存儲(chǔ)卡平酿,可以訪問。
涉及源碼
StorageManagerService (如下簡(jiǎn)稱SMS)
VoldConnector
Vold (system/vold)
分析
-
首先看mount結(jié)果受葛,與正常設(shè)備做對(duì)比题涨,發(fā)現(xiàn)問題設(shè)備沒有掛載/data/media
雖然有區(qū)別, 但是無法看出問題所在总滩。
-
對(duì)比SMS中開機(jī)時(shí)發(fā)送的vold指令
此處發(fā)現(xiàn)纲堵,問題設(shè)備(左)沒有發(fā)送下面的命令
SND -> {5 volume mount emulated 3 -1}
這也是解決此問題的關(guān)鍵。
-
分析SMS的源碼闰渔,發(fā)現(xiàn)有兩處會(huì)發(fā)送 volume mount 指令給vold席函。
一處是mount函數(shù),這個(gè)函數(shù)一般是通過StorageManager然后通過binder調(diào)用過來的冈涧,更多時(shí)候是給其他service茂附,乃至APP使用,所以分析時(shí)我認(rèn)定此處不是觸發(fā)volume mount命令的根源督弓,通過添加log也確認(rèn)了此想法营曼。
另一處,是SMS中的handler收到H_VOLUME_MOUNT消息時(shí)發(fā)出的
-
分析H_VOLUME_MOUNT的發(fā)出愚隧,這個(gè)消息的發(fā)出也有好幾處地方蒂阱,通過添加log,確認(rèn)在onVolumeCreatedLocked函數(shù)中發(fā)出,但是這里也有好幾個(gè)分支
通過分析更多的log录煤,正常和異常設(shè)備虱痕,開始時(shí)都會(huì)調(diào)用兩次onVolumeCreatedLocked,并且有兩種type都會(huì)調(diào)用辐赞,TYPE_EMULATED和PUBLIC部翘,但是通過第3步中命令對(duì)比,可以發(fā)現(xiàn)問題出現(xiàn)在TYPE_EMULATED這個(gè)if分支中响委,異常設(shè)備中新思,并沒有發(fā)出SND -> {5 volume mount emulated 3 -1}
原因就是正常設(shè)備中,mPrimaryStorageUuid這個(gè)字段開機(jī)時(shí)會(huì)被初始化為null赘风,而異常設(shè)備不會(huì)夹囚。如下log
異常設(shè)備
正常設(shè)備
所以在異常設(shè)備中,因?yàn)閙PrimaryStorageUuid這個(gè)字段的存在邀窃,導(dǎo)致無法執(zhí)行正確的代碼邏輯荸哟,沒有發(fā)出SND -> {5 volume mount emulated 3 -1}指令。
- mPrimaryStorageUuid 這個(gè)字段的賦值瞬捕,這個(gè)字段是在SMS的構(gòu)造函數(shù)中完成初始化的鞍历,SMS的構(gòu)造函數(shù)調(diào)用了readSettingsLocked函數(shù),在這個(gè)函數(shù)中肪虎,會(huì)解析 /data/system/storage.xml文件劣砍,在讀到<volumes>標(biāo)簽時(shí),給mPrimaryStorageUuid賦值扇救,從如下文件內(nèi)容看刑枝,異常設(shè)備中是有值的。
異常設(shè)備
2|rk3399:/data/system # cat storage.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<volumes version="3" primaryStorageUuid="b3929278-9b6d-42b4-bc36-25624ac57088" forceAdoptable="false">
<volume type="0" fsUuid="5892-50F7" userFlags="1" createdMillis="1596803101624" lastTrimMillis="0" lastBenchMillis="0" />
<volume type="0" fsUuid="A228-275C" userFlags="1" createdMillis="1592010634266" lastTrimMillis="0" lastBenchMillis="0" />
<volume type="1" fsUuid="b3929278-9b6d-42b4-bc36-25624ac57088" partGuid="785A63E9-AB9F-4EC6-AB3C-7835858B887D" nickname="SanDisk SD 卡" userFlags="0" createdMillis="1592011533004" lastTrimMillis="0" lastBenchMillis="1592011548005" />
<volume type="0" fsUuid="6636-3230" userFlags="0" createdMillis="1591193458084" lastTrimMillis="0" lastBenchMillis="0" />
<volume type="0" fsUuid="6437-3432" userFlags="0" createdMillis="1591776505636" lastTrimMillis="0" lastBenchMillis="0" />
</volumes>
正常設(shè)備
rk3399:/data/system # cat storage.xml
<volumes version="3" forceAdoptable="false">
<volume type="0" fsUuid="5892-50F7" userFlags="0" createdMillis="1573013876754" lastTrimMillis="0" lastBenchMillis="0" />
<volume type="0" fsUuid="8765-4321" userFlags="0" createdMillis="1592815201367" lastTrimMillis="0" lastBenchMillis="0" />
</volumes>
- 總結(jié)
該問題的解決迅腔,可以通過刪除 data/system/storage.xml 并重啟設(shè)備 來完成装畅,這樣SMS會(huì)重新寫這個(gè)文件。
但是出現(xiàn)該問題的原因還無法確定沧烈,因?yàn)槌霈F(xiàn)問題時(shí)的log已經(jīng)沒有掠兄,即便有,相關(guān)信息也比較少掺出,無法定位徽千。
我分析比較可能的原因是插入了一個(gè)android設(shè)備無法識(shí)別(可能是格式問題)的外置存儲(chǔ)卡導(dǎo)致,并且從storage.xml中可以看到汤锨,異常的uuid是很長(zhǎng)一大串的隨機(jī)數(shù)双抽,一些正常的外置卡,則比較規(guī)律闲礼。