1. 程式人生 > >android系統中修改sd卡掛載目錄

android系統中修改sd卡掛載目錄

這段時間,一直在弄Android系統上的SD掛載。那為什麼要鼓搗Android系統的SD掛載呢?下面不得不從開始說起。

一、Android系統掛載位置SD卡現狀。

Android系統預設掛載的外接SD與首選(primary)的外接儲存裝置的路徑是並列。USB儲存裝置同樣也與這兩種儲存裝置並列。比如三種外接儲存裝置掛載路徑如下:

1) 首選外接儲存裝置掛載路徑:/mnt/sdcard(我的首選外接儲存裝置為系統自帶的Nand,大小2G多)。

2) 外接SD卡的掛載路徑:/mnt/external_sd(系統自帶一個SD卡槽,供使用者擴充套件)。

3) 外接USB儲存裝置掛載路徑:/mnt/usb_storage(

系統自帶一個USB介面,供使用者使用)。

而在Android4.0及Android4.1的系統中,僅提供了一個獲取首選外接儲存裝置路徑的API。對於除首選的外接儲存裝置外,Android並沒有提供標準的方法給應用程式訪問。在這種情況下,對於我的系統,首選外接儲存裝置的大小有限。這樣對於較大的應用程式,比如一些導航軟體來說,我可能會想到把一些較大的地圖資料放到我的外接的SD卡中,而只有應用安裝到我系統的內建儲存裝置或首選SD卡中。這時,應用程式沒有標準的方法來訪問我的外接SD卡。出現了矛盾。

二、解決矛盾的思路。

縱觀當前流行的導航軟體,它們會去/mnt/sdcard/external_sd中搜索自己認識的目錄。而並不去/mnt/external_sd目錄中搜索。這樣有了解決方法,就是在/mnt/sdcard/目錄下建立一個external_sd目錄,這個目錄與外接SD中的內容同步。這樣就有了兩種方法:

1) 在/mnt/sdcard/目錄下建立一個軟連線連線到/mnt/external_sd目錄。

2) 在/mnt/sdcard/目錄下建立一個external_sd目錄,並將外接的SD卡掛載到/mnt/sdcard/external_sd目錄下。

這兩種方法首先說第一種方法,也就是建立軟連線的方法。因為我的/mnt/sdcard掛載了首選的儲存裝置,這個儲存裝置格式化為vfat格式。而fat/vfat等這樣的檔案系統不支援symlink函式。所以放棄了這種方法。

而對於第二種方法,要做的的事情可就多了。如果想要了解Android系統中的儲存裝置掛載流程,可以在網上搜索以下。我這裡提供一個我參考的文章:

http://blog.csdn.net/yihongyuelan/article/details/6926034

三、解決問題過程

下面說說我是怎麼掛載我的外接SD卡到/mnt/sdcard/external_sd目錄的過程。

1) 在系統原始碼中將所有/mnt/external_sd修改為/mnt/sdcard/external_sd。

你可以使用Android提供個resgrep、jgrep來個命令來搜尋相關的資源。當然你也可以使用下面的命令來搜尋相關的關鍵字:

Find . –name “*.*”| xargs grep “external_sd” –color [email protected]

這樣其實就可以修改外接SD卡的掛載目錄了,但是這裡有一個問題。因為外接的SD卡的掛載是以首選儲存裝置掛載完成為基礎。所以要首先確保首選儲存裝置已經掛載上,然後再去掛載外接SD卡。同理,解除安裝的時候要先確保外接SD卡先解除安裝。下面說明我對原始碼的修改過程及遇到的一些問題。

1. 修改SD卡的掛載路徑。

Android系統儲存裝置的掛載路徑主要由vold.fstab檔案決定。它告訴系統怎麼去掛載外部儲存。在Android原始碼中有很多vold.fstab,比如我的原始碼中就有以下檔案:

./device/samsumg/crespo/vold.fstab

./device/moto/wingray/vold.fstab

./device/rockchip/rk30sdk/vold.fstab

./system/core/rootdir/etc/vold.fstab

到底哪個是呢?當然是你所使用平臺所相關的那個vold.fstab。我用的是Rockchip的CPU,所以與我相關的vold.fstab檔案為./device/rockchip/rk30sdk/vold.fstab。對於/system/core/rootdir/etc/vold.fstab,我也不很清楚是做什麼的。我認為是google給我們的一個參考的例子。有清楚的人請一定告訴我。在這個檔案我把/mnt/external_sd(外接SD卡的掛載路徑)修改為/mnt/sdcard/external_sd(Nand的掛載路徑,意思是把外接SD卡掛載到Nand的目錄下)。這樣一個簡單的修改,系統就知道怎麼掛載外接的儲存裝置了。

現在系統雖然知道怎麼掛載,我們還得給它建立好掛載點,否則它不會隨便掛載的。就好像你知道怎麼燒水,但是沒有火爐子你就不知道把水壺放到什麼地方燒。那麼現在咱們就來建立掛載點。

修改以下檔案:

./device/rockchip/rk30sdk/init.rk30board.rc

. /device/rockchip/rk30sdk/recovery.fstab

. /device/rockchip/rk30sdk/recovery/etc/init.rc

將上面檔案中的/mnt/external_sd修改為/mnt/sdcard/external_sd。

為了小心一點,我在init.rk30board.rc檔案中通過symlink命令建立一個軟連線到/mnt/external_sd。這種情況symlink命令是支援的。因為你建立的軟連線是在ext4檔案系統上的。如下:

symlink /mnt/sdcard/external_sd /mnt/external_sd

好了,現在算是把掛載點建立好了,但是上層是不是有地方用到/mnt/external_sd這樣的絕對路徑呢?用Find . –name “*.*” | xargs grep “/mnt/external_sd ” –color [email protected]命令搜尋一下,可以看到的確有地方用啊:

./device/rockchip/rk30sdk/overlay/frameworks/base/core/res/res/xml/storage_list.xml

./framework/bash/services/java/com/android/server/MountService.java

./packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerService.java

同樣,將上面檔案中的/mnt/external_sd修改為/mnt/sdcard/external_sd。

至此,SD的掛載的目錄已經被修改為/mnt/sdcard/external_sd。

雖然說掛載路徑已經修改完成了,但是有可能系統並沒有正確掛載上SD卡。下面說說我遇到的問題以及解決方法。

現在make以下,燒一遍,發現沒有掛載上…為什麼呢?下面來說這個問題。

1. 上面已經告訴系統如何掛載外接儲存裝置並且已經把掛載點建立好了,那為什麼還掛載不上去呢?

這個可把我難住了。但是不怕。我們在原始碼中加trace,看看系統到底是如何掛載的,怎麼他就不聽話呢?經過80難終於發現了那個小bug。

案發現場:Nand掛載正常。/mnt/external_sd目錄已經變成了軟連線了,但是它的連結目標不存在。/mnt/sdcard/目錄下不存在external_sd目錄。

推理思路:難道掛載點沒有建立成功?找到./system/vold/main.cpp,通過open()函式開啟/mnt/sdcard/external_sd,發現系統在解析init.rk30board.rc檔案後已經建立了/mnt/sdcard/external_sd目錄。open成功。並且在./system/vold/main.cpp中while(1)之前這個目錄都存在。那看來系統已經建立了這個掛載點了,但是不知道哪裡把掛載點弄沒了。順著sd卡掛載流程加trace,終於讓我找到了,原來系統建立的/mnt/sdcard/external_sd在系統掛載Nand(Nand的掛載路徑為/mnt/sdcard)完成後就被覆蓋了。知道這一點了,那麼我就有辦法了:在Nand掛載完成後用mkdir函式在/mnt/sdcard/目錄下再建立一次SD卡的掛載路徑。

編譯,燒錄。又有問題了…..

2. 上面可算是把掛載點建立好了,但是問題有出在哪裡了呢?下面說明現場情況。

案發現場:Nand掛載正常,/mnt/external_sd軟連線和/mnt/sdcard/external_sd都存在了。在系統啟動後插入SD卡,系統可正常掛載。插著SD卡重啟系統,SD卡掛載失敗。各個目錄仍然存在。為什麼SD卡得不到系統的青睞?Nand到底與SD卡有何深仇大恨呢?非要置SD卡與死地?下面請繼續收看…

那麼大家請繼續聽我扯。經過詳細的偵察發現,原來系統啟動的時候,最先掛載是不是Nand,而是SD卡。這樣怪不得人家系統,Nand是後媽養的,SD卡人家是親生的。這樣的順序就導致本來已經掛載上的SD卡(掛載目錄/mnt/sdcard/external_sd)被後來掛載的Nand覆蓋。沒辦法,Nand是老大,沒有老大(在storage_list.xml檔案中android:primary="true"),老二就不應該出來。

既然這樣,我就強制把你掛載的順序調整一下。保證兩個都能正常掛載上。那怎麼調整呢?在./system/vold/VolumeManager.h檔案中增加五個成員變數如下:

其中

sIsFlashMounted表示Nand是否已經掛載完成。如果掛載完成則為true,否則為false。

sIsHavaSD表示是否有SD請求掛載。如果有則為true,否則為false。

sIsSdMounted表示SD是否已經掛載完成,如果掛載完成則為true,否則為false。

sIsHavaUsb對於Usb的掛載,未使用到。

mMountingSD為請求掛載的SD的Volume類。

在./system/vold/VolumeManager.cpp檔案修改mountVolume方法。


修改unmountVolume方法:

注意,如果只修改mountVolume不修改unmountVolume,在使用“開啟USB儲存裝置”的功能時,會有問題。

至此,經過81難,SD的掛載終於成功。

一、 改變SD卡掛載路徑帶來的問題及解決方法:

1) 問題一:點選Setting-〉儲存,Setting程式崩潰。

解決思路:經過trace跟蹤發現,是framework/base/core/jni/android_os_StatFs.cpp層的statfs函式執行時沒有許可權造成的。這樣需要給/mnt/sdcard/目錄讀和執行的許可權。

解決方法:在./system/vold/Volume.cpp檔案中的intVolume::mountVol() 函式中掛載Nand的時候,修改其許可權掩碼permMask 0702為0202.

2) 問題二:在Setting-〉儲存選項中如果解除安裝Nand,Setting會崩潰。

解決思路:Nand本來就在系統內部。沒有必要讓使用者解除安裝。所以可以把Setting-〉儲存下NAND FLASH項下的“解除安裝儲存裝置”隱藏掉。

解決方法:修改

packages/apps/Settings/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java檔案。將該檔案中所有使用到mMountTogglePreference變數處的程式碼都加上如下條件:

if((mStorageVolume == null)||(!(mStorageVolume.getPath().equals("/mnt/sdcard"))))

如下圖為其中一處修改:

也就是判斷如果要檢查的外接裝置為Nand Flash,則不顯示“解除安裝儲存裝置”選項。

3) 問題三: 如果使用了Android系統的“開啟USB儲存裝置”功能,當所有裝置都已USB儲存裝置開啟後,再進入Setting-〉儲存,Setting崩潰。

解決思路:通過trace(adb logcat)發現,這種情況下,Nand和SD卡都已經自動解除安裝下來。在/mnt/目錄下為init.rc和init.rk30board.rc檔案建立的目錄。/mnt/sdcard和/mnt/sdcard/external_sd兩個目錄的使用者組和許可權都有以上兩個檔案中相關命令確定。這時由於/mnt/sdcard/目錄許可權為0000. statfs函式沒有許可權讀取/mnt/sdcard/external的資訊,造成Setting崩潰。

解決方法:需要給/mnt/sdcard目錄讀和執行的許可權。修改下面兩個檔案:

./device/rockchip/rk30sdk/init.rc

./device/rockchip/rk30sdk/init.rk30board.rc

在mkdir/mnt/sdcard 和mkdir /mnt/sdcard/external_sd的地方,將許可權修改為0500.

修改init.rc:

修改init.******board.rc:

4) 問題四:刪除使用絕對路徑/mnt/external_sd的RkExplorer.apk。因為Rockchip自己寫的資源管理器的程式碼中使用了絕對路徑,而當我們修改了SD卡的掛載路徑後,這個APK總是崩潰。而在Android系統中,資源管理器這樣的軟體,完全可以讓使用者自己安裝,所以我們可以刪除這個軟體。

相關推薦

android系統修改sd掛載目錄

這段時間,一直在弄Android系統上的SD掛載。那為什麼要鼓搗Android系統的SD掛載呢?下面不得不從開始說起。 一、Android系統掛載位置SD卡現狀。 Android系統預設掛載的外接SD與首選(primary)的外接儲存裝置的路徑是並列。USB儲存裝置同樣也與這兩種儲存裝置並列。比如三種外接儲

Android 監控(檢查)SD指定目錄的變化

Android 開發有時候需要檢測某個資料夾的變化,就可以使用 FileObserver這個類。 FileObserver這個類是系統自帶的,可以直接使用。  private FileObserver mFileObserver;   String p

詳解Android獲取SD和記憶體的空間資訊

建立一個新的Android工程,工程名字為《獲取儲存空間大小》,包名為:com.connect.storageSize 這裡使用預設生成的佈局檔案和Activity類。 修改佈局檔案activity_main.xml 佈局檔案第二部分: 編寫業務程式碼 業務程式碼第一部分: 業務程

修改Android系統/system的讀寫許可權

這段時間一直在修改sd卡的host controller的驅動,並於昨天重新編譯了核心並fastboot到g5手機中,sd卡是可以讀出來了,看樣子驅動生效了,興奮之餘看看同樣使用sd host控制的wifi,遺憾的wifi出錯,後來查明原因是: 編譯核心使用的是預設的msm

OS X 系統修改webstorm的默認瀏覽器

png file 應用 wid 分享 人的 設置 row web 大多數人的問題產生於沒有找到os x 系統中webstorm的setting選項。 首先要知道再os x系統中,所有的系統偏好設置均以“preference”呈現。在webstorm中,setting選項並不

Android推斷是否有sd

true name ng- rac 是否 例如 推斷 str article 推斷手機上是否有SD卡存在。作為經常用法,寫到工具類裏,用時直接調用。代碼例如以下: public static boolean hasSdcard(){ String

Linux系統修改/etc/profile文件的方法

linux在Linux系統中etc/profile文件一般是不能更改的,想要更改etc/profile文件就要用一些特殊的技巧進行Linux文件修改。本文就來介紹一下Linux系統中修改/etc/profile文件的方法:etc/profile文件是只讀的,直接用vi或gedit打開修改後是無法保存的。要修改

linux系統修改文件夾目錄權限-chmod

inux 文字 順序 tex 一個 lpad 主目錄 有用 add Linux、Fedora、Ubuntu修改文件、文件夾權限的方法差不多。很多人開始接觸Linux時都很頭痛Linux的文件權限問題。這裏告訴大家如何修改Linux文件-文件夾權限。以主文件夾下的一個名為cc

linux系統修改密碼報錯的問題

ali 解決 ria 字典 pre ren sele show 規則 1、mysql密碼報錯的原因 報錯信息 ERROR 1819 (HY000): Your password does not satisfy the current policy requirement

Android 獲取手機模擬器sd圖片及擷取圖片

需把圖片儲存到找到手機模擬器(夜神模擬器)sd卡中的圖片路徑:檔案管理器/mnt/sdcard/images(images是自己創的資料夾) java程式碼: package com.example.android_07; import android.graphics.Bitmap

Android系統main.mk關於RCS和SCCS的解釋

# this turns off the RCS / SCCS implicit rules of GNU Make % : RCS/%,v % : RCS/% % : %,v % : s.% % : S

在泛微系統修改AD密碼

-s 一個 itl windows 證書頒發機構 net image imp 中心 參照文檔: Windows server 2008 R2 安裝AD域證書:https://blog.csdn.net/zhuyongru/article/details/81107839 配

Android獲取外接SD讀寫路徑

1. 外接SD卡的一些問題 1.1 關於外接SD卡上的讀寫路徑 Android 4.4及以上版本,應用的外接SD卡讀寫路徑被限定在固定路徑上(外接SD卡根路徑/Android/data/包名/files)。 Android4.4以下版本,申請了外接SD卡讀寫許可權的應用在整個

Android系統手動修改系統顯示的DPI

有時候開發系統在初期階段由於UI設計上存在問題,導致DPI需要調整滿足UI介面的美觀,需要通過adb手動需要DPI,除錯OK之後將DPI值固定在程式碼中,如下: 手動修改DPI: 進入 adb roo

Android gradle build 修改檔名稱及目錄

Android gradle build 修改檔名稱及目錄 android 在build的時候.輸出apk的位置在於工程目錄下的build資料夾下,名稱也是固定的,但是在某些場景下需要對apk進行重名稱,比如名稱裡含有當時間build的時間,或者把檔案輸出的目錄放到桌面上.這裡就說一

Android系統ls -al 資訊說明

   在Android系統中我們檢視目錄下檔案資訊會用到命令 ls -al 展現出如下基本資訊. drwxrwxrwt 16 root root 680 2018-08-16 17:14 . drwxrwxrwt 16 root root 680 20

Linux根檔案系統的比較常見的目錄結構

/bin 存放二進位制可執行命令的目錄 /dev 存放裝置檔案的目錄 /etc 存放系統管理和配置檔案的目錄 /home 使用者主目錄,比如使用者user的主目錄就是/home/user,可以用~user表示 /lib 存放動態連結共享庫的目錄 /sbin存放系

Android系統實現AIDL 自定義物件傳遞

  今天要在《在Android系統中實現AIDL介面回撥》這篇文章的基礎上實現AIDL自定義物件的傳遞功能。還是上一篇說到的三個專案: ├── SimpleJar ├── SimpleJarClient └── SimpleJarService 一、在SimpleJar專

android系統如何通過程式開啟某個AccessibilityService

android系統中如何通過程式開啟某個AccessibilityService(系統輔助服務)?通常的做法是註冊AccessibilityService(輔助服務)後跳轉到設定啟動服務頁面引導使用者手動將我們建立的AccessibilityService開啟。但是很多android系統過段時間會自動將Acc

如何驗證Android系統APK證書鏈的有效性

瀏覽器通過https訪問指定網址時, 需要驗證網站的證書, 瀏覽器中通常內建常用的CA(Certificate Authority)根證書,而網站的證書一般都是由根CA或者子CA簽名的.如果網站沒有這些知名CA簽名, 則需要將網站自己的根證書匯入瀏覽器才能進行h