從Android6.0開始,Android支持移動存儲(adoptable storage),例如SD卡或者USB。移動存儲可以像內部存儲一樣加密和格式化,可以存儲所有類型的應用數據。
## 權限
是否訪問外部存儲由各種Android權限保護。
* 從Android1.0開始,寫訪問需要 WRITE_EXTERNAL_STORAGE 權限;
* 從Android4.0開始,讀訪問需要READ_EXTERNAL_STORAGE。
* 從Android4.4開始,外部存儲設備上的文件,也能夠基于目錄結構來合成(synthesized )不同的DAC權限(owner,group,mode)。這容許應用能夠在外部存儲上管理一個包相關的目錄,而無需WRITE_EXTERNAL_STORAGE 。例如, 應用com.example.foo 可以自由訪問外部存儲上的Android/data/com.example.foo/。這種合成權限是通過fuse守護來包裹原始存儲設備來完成的。
## 運行時權限
Android6.0 引入了新的運行時權限(runtime permissions)模型,用于應用在運行中必要時申請權限。由于新模型包含了READ/WRITE_EXTERNAL_STORAGE,因此平臺需要在不殺死或者重啟運行中的應用的前提下,動態對存儲訪問授權。這是通過維護所有掛載的存儲設備的三個不同視圖來實現的:
* /mnt/runtime/default 對所有的應用、root名字空間(adb 和其他系統組件)可見,而無需任何權限
* /mnt/runtime/read 對有READ_EXTERNAL_STORAGE權限的應用可見。
* /mnt/runtime/write 對有WRITE_EXTERNAL_STORAGE權限的應用可見。
在zygote fork時,我們為每個運行中的應用創建一個mount名字空間,在其中bind mount合適的初始視圖。然后,當被授予運行時權限時,vold在運行中的應用的名字空間上,通過bind mount來更新視圖。注意,如果權限被撤銷,將意味著該應用被kill。
系統使用**setns()**函數來實現上述特性,這要求Linux3.8,不過Linux3.4加上補丁上也可以支持該功能。
在Android6.0中,第三方應用不再被加入sdcard_r和sdcard_rw組中。相反,通過給應用掛載合適的**運行時視圖**,實現對外部存儲的訪問控制。同時,使用everybodyGID來進行的跨用戶交互被禁止了。