1、前言
在Android系統中使用啟動腳本.rc文件,可以在系統的初始化過程中進行一些簡單的初始化操作,這些初始化啟動腳本.rc文件直接被安裝到目標板的根文件系統中,例如,init.rc啟動腳本被init可執行程序進行解析,本文將簡單介紹如何在MSM8953平台的Android系統中添加我們自己的啟動腳本.rc文件。
2、Android添加啟動腳本
關於.rc啟動腳本的語法在本篇文章中將不會介紹,只介紹如何對Android源碼進行修改,並在我們的目標板中添加啟動腳本.rc文件的基本流程,我們需要添加的啟動腳本為:
init.test.rc
需要添加到目標板系統的目錄為:
/vendor/etc/init/hw/
接下來,將對在Android系統中添加啟動腳本的流程進行分析:
進入到需要修改的目錄下,如下命令:
$ cd msm8953_9.0/device/qcom/msm8953_64
修改該目錄下的AndroidBoard.mk文件,可以使用vim編輯器或者其它軟件:
$ vim AndroidBoard.mk
修改如下所示:

該代碼表示要對init.test.rc文件進行編譯,其中LOCAL_MODULE表示模塊的名稱,直接為文件的名稱,LOCAL_SRC_FILES表示源文件的路徑,在上面表示為當前目錄,因此,我們需要在當前的目錄下面,新創建我們需要添加的init.test.rc文件,LOCAL_MODULE_PATH表示目標文件打包在目標板系統的哪個路徑,在上面表示,打包的路徑為/vendor/etc/init/hw/,修改完成后,保存即可。
接下來修改該目錄下的msm8953_64.mk文件,命令如下:
$ vim msm8953_64.mk
修改文件如下:

在上面的代碼中,我們定於了一個變量TEST_INIT,然后變量的內容為我們需要添加的模塊的名稱,PRODUCT_PACKAGES為全局變量,表示編譯時候需要打包的內容,在這里,我們需要把我們定於的模塊,也就是要添加的啟動腳本添加進去,否則的話,將不會進行編譯,修改完成后,保存即可。
接下來修改該目錄下的init.target.rc文件,命令如下:
$ vim init.target.rc
修改文件如下:

在這里,表示需要把我們新添加的init.test.rc文件導入,注意文件的路徑,這里是目標板系統中的文件的路徑,否則的話,腳本文件將不能啟動。
接下來,當前的目錄下,新創建我們需要添加的啟動腳本init.test.rc文件,如下命令:
$ touch init.test.rc $ vim init.test.rc
在init.test.rc文件中添加下面的內容:

在上面的代碼中,定於了一個觸發動作,觸發的條件為:
sys.boot_completed=1
也就是當系統的屬性sys.boot_completed為1的時候(系統啟動完成),該動作將會被觸發,其下面的語句也將會被逐句執行,語句的含義解析如下:
write /sys/class/gpio/export 0
表示在sysfs中導出gpio0引腳。
write /sys/class/gpio/gpio0/direction out
表示將gpio0引腳的方向設置為輸出方向,該方向能控制gpio引腳的高低電平。
write /sys/class/gpio/gpio0/value 1
表示將gpio0引腳的電平設置為高電平。
chmod 764 /sys/class/gpio/gpio0/value
該句則表示將value的訪問屬性修改為擁有者可讀可寫可執行,組可讀可寫,其他人只能讀。
啟動腳本init.test.rc文件修改完成,接下來重新編譯Android系統,檢查輸出文件中是否已經生成了我們添加的啟動腳本:
$ cd msm8953_9.0/out/target/product/msm8953_64/vendor/etc/init/hw
$ ls -al
輸出如下,說明新添加的啟動文件init.test.rc已經成功被打包進系統了:

接下來,將編譯后的鏡像文件重新燒寫到目標板中,然后對目標板重啟,檢查kernel的啟動log看是否已經啟動了我們新添加的啟動腳本:
$ su root # dmesg | grep "init.test.rc"
輸出如下,表示啟動腳本init.test.rc已經被成功加載了,並且定義的動作已經被成功觸發:

也可以檢查對應的目錄下,是否具有我們的啟動腳本init.test.rc:
# cd /vendor/etc/init/hw
# ls -al
輸出如下,說明新添加的init.test.rc文件已經存在當前啟動的Android系統中了:

最后,檢查動作觸發后,執行的內容是否正確,也就是檢查gpio0這個引腳是否被導出sysfs中,方向是否為輸出,當前的電平值是否為高電平:
# cd /sys/class/gpio # ls -l
輸出如下,表示gpio0已經成功被導出:

接下來,檢查gpio0的方向以及當前的電平值:
# cd gpio0 # cat direction # cat value # ls -l value
輸出如下,說明定義在動作下的語句都被成功執行了:

至此,我們就已經實現了在Android系統中添加自己定於的啟動腳本init.test.rc文件了。
3、腳本中啟動一個簡單的服務
對於Android系統中的.rc文件,我們除了可以定義一些動作(Action)以外,還能進行一些服務(Service)定義。
在上面,我們已經成功實現了在Android系統中添加我們自己定義的啟動腳本init.test.rc文件,接下來,我們將在此基礎上,繼續修改文件,在啟動腳本中添加一個簡單的服務,當我們的啟動腳本文件init.test.rc被解析的時候,把我們自己定義的服務進行啟動。
進入到需要修改的Android源碼目錄下,如下:
$ cd msm8953_64/device/qcom/msm8953_64
修改該目錄下的AndroidBoard.mk文件,將我們自己定義的.sh腳本進行編譯,修改如下:

該代碼表示要對init.test.boot.sh,也就是模塊進行編譯,源文件為當前路徑的init.test.boot.sh文件,LOCAL_MODULE_PATH表示為模塊生成在目標板的路徑,定義為TARGET_OUT_VENDOR_EXECUTABLES變量的值,也就是下面的路徑:
/vendor/bin/
接下來,修改當前目錄的msm8953_64.mk文件,將我們定於的.sh文件進行打包編譯:
$ vim msm8953_64.mk
修改如下:

接下來,修改前面添加的init.test.rc文件,定義我們需要添加的服務:
$ vim init.test.rc
修改如下:

該服務比較簡單,分析一下吧,service關鍵字表示我們需要定義一個服務,服務的名稱為test_boot-sh,當屬性sys.boot_completed被設置為1后,啟動我們自己定義的服務,服務啟動后執行的.sh文件為:
/vendor/bin/init.test.boot.sh
class core表示當core服務起來后,該test_boot-sh服務也將被啟動,oneshot表示該服務只執行一次。
接下來,在當前目錄下,新創建init.test.boot.sh文件,並添加我們簡單的測試代碼:
$ touch init.test.boot.sh $ vim init.test.boot.sh
.sh文件編輯如下:

從上圖看到,新創建的.sh文件要做的事情很簡單,只是輸出一個字符串提示,用來說明我們自己添加的服務已經成功啟動了。
此外,想要成功運行init.test.boot.sh,還需要解決該文件運行的SELinux的策略問題,否則的話,服務將啟動不成功,修改如下:
$ cd msm8953_9.0/device/qcom/sepolicy/vendor/msm8953 $ vim file_contexts
文件修改如下:

代碼添加修改完成后,重新編譯鏡像文件,並檢查init.test.boot.sh文件是否已經被編譯了:
$ cd msm8953_9.0/out/target/product/msm8953_64/vendor/bin $ ls -l
輸出如下所示,表示.sh文件已經被成功編譯打包了:

接下來,還需要檢查.sh文件的SELinux策略是否已經被添加,對於vendor下的sepolicy,如下查看:
$ cd msm8953_9.0/out/target/product/msm8953_64/vendor/etc/selinux $ vim vendor_file_contexts
如下所示,說明sepolicy已經被成功添加了:

接下來將鏡像文件重新打包並燒寫到目標板中重啟系統,檢查一下我們添加的服務是否已經正常啟動:
先來檢查一下,目標板對應的系統中是否存在init.test.boot.sh文件:
# cd /vendor/bin # ls -al *.sh
輸出如下,表示文件存在:

接下來,檢查kernel的啟動log,看我們的服務是否已經成功加載:
# dmesg | grep Service
輸出如下,說明我們自己添加的Service已經成功啟動了:

4、小結
本文主要簡單介紹了如何在MSM8953平台的Android系統中添加自己定於的啟動腳本.rc文件,並嘗試添加自己定義的服務。
