1、Android的HAL是為了一些硬件提供商提出的“保護(hù)proprietary”的驅(qū)動(dòng)程序而產(chǎn)生的東東,簡(jiǎn)而言之,就是為了避開Linux kernal的GPL license的束縛。Android把控制硬件的動(dòng)作都放到了user space中,而在kernel driver里面只有簡(jiǎn)單的讀寫寄存器的操作,而完全去掉了各種功能性的操作(比如控制邏輯等),這些能夠體現(xiàn)硬件特性的操作都放到了Android的HAL層,而Android是基于Aparch的license,因此硬件廠商可以只提供二進(jìn)制代碼,所以說Android知識(shí)一個(gè)開放的平臺(tái),并不是一個(gè)開源的平臺(tái)。
2、Android的HAL的實(shí)現(xiàn)需要通過JNI(Java Native Intereface),JNI簡(jiǎn)單說就是java程序可以調(diào)用C/C++寫的動(dòng)態(tài)鏈接庫,這樣的話,HAL可以使用C/C++語言編寫,效率更高。而Android的app可以直接調(diào)用.so,也可以通過app->app_manager->service(java)->service(jni)->HAL來調(diào)用。第二種方法看上去很復(fù)雜,但是更加符合android的架構(gòu)結(jié)構(gòu)。Android的HAL,從底層往上層。
3、Android的HAL,從底層往上層講
(1)Kernel Driver
這里的kernel driver相對(duì)于linux真正的driver形式上是一樣的,也提供open,read,write,ioctl,mmap等接口,就可以只作成往寄存器寫操作,至于如何寫,為什么寫,這些工作都會(huì)在HAL層進(jìn)行的,而一般用戶是看不到這些代碼的。這也是linux mainstream把a(bǔ)ndroid的kernel踢出去的原因,因?yàn)檫@些driver根本無法用在其他的linux平臺(tái)上。
(2)這一層就位于kernel之上的user space了,一般來說這里需要涉及的是兩個(gè)結(jié)構(gòu)體:hw_module_t和hw_device_t,第一個(gè)結(jié)構(gòu)體是當(dāng)這個(gè)hardware stub被load的時(shí)候(hw_get_module())提供的初始化操作,比如提供stub的open(module->methods->open())操作,而第二個(gè)結(jié)構(gòu)體是提供該硬件stub具有的操作硬件的接口,,在jollen的mokoid工程里,主要提供打開和關(guān)閉led的操作,文件就是led.h和文件led.c,這兩個(gè)文件后會(huì)被編譯成動(dòng)態(tài)鏈接庫,不如libled.so被放到/system/libs/hw/,當(dāng)service調(diào)用hw_get_module(hardware/libhardware/hardware.c)時(shí),會(huì)在/system/libs/hw/里面尋找對(duì)應(yīng)的動(dòng)態(tài)鏈接庫,然后提供給service對(duì)應(yīng)的操作接口。
Process and Lifecycle該優(yōu)先權(quán)分五層。下面的列表顯示優(yōu)先權(quán)層次順序:
前景進(jìn)程
可視進(jìn)程
服務(wù)進(jìn)程
背景進(jìn)程
空進(jìn)程
4、學(xué)習(xí)不同的語言如何進(jìn)行協(xié)作,尤其是如何實(shí)現(xiàn)垃圾回收和多線程。把一個(gè)虛擬機(jī)實(shí)現(xiàn)整合到用C/C++寫的程序中。系統(tǒng)環(huán)境代指本地操作系統(tǒng),它有自己的本地庫和CPU指令集。本地程序(Native Applications)使用C/C++這樣的本地語言來編寫,被編譯成只能在本地系統(tǒng)環(huán)境下運(yùn)行的二進(jìn)制代碼,并和本地庫鏈接在一起。本地程序和本地庫一般地會(huì)依賴于一個(gè)特定的本地系統(tǒng)環(huán)境。只有在同一進(jìn)程中調(diào)用本地代碼時(shí),使用JNI。
5、使用JAVA程序調(diào)用C函數(shù)來打印“、helloworld!",這個(gè)過程包含下面幾步:
(1)創(chuàng)建一個(gè)類(Hello World.java)聲明本地方法。在Java代碼中聲明本地方法必須有“native”標(biāo)識(shí)符,native修飾的方法,在java代碼中只作為聲明存在。在調(diào)用本地方法前,必須首先裝載含有該方法的本地庫。如HelloWorld.java中所示,置于static塊中,在Java VM初始化一個(gè)類時(shí),首先執(zhí)行這部分代碼,這可保證用本地方法前,裝載了本地庫。
(2)使用javac編譯源文件HelloWorld.java,產(chǎn)生HelloWorld.class。使用javah -jni來生成C頭文件(HelloWorld.h),這個(gè)頭文件里面包含了本地方法的函數(shù)原型。
(3)用C代碼寫函數(shù)原型的實(shí)現(xiàn)。
(4)把C函數(shù)實(shí)現(xiàn)編譯成一個(gè)本地庫,創(chuàng)建Hello-World.dll或者libHello-World.so。
(5)使用java命令運(yùn)行HelloWorld程序,類文件Hello-World.class和本地庫在運(yùn)行時(shí)被加載。
6、開發(fā)者使用JNI時(shí)常問到的是JAVA和C/C++之間如何傳遞數(shù)據(jù),以及數(shù)據(jù)類型之間如何互相映射。
Java_HelloWorld_print(JNIEnv *,jobject);該函數(shù)聲明,接受兩個(gè)參數(shù),而對(duì)應(yīng)的Java代碼對(duì)該函數(shù)的聲明沒有參數(shù),第一個(gè)參數(shù)是指向JNIEnv結(jié)構(gòu)的指針;第二個(gè)函數(shù),為HelloWorld對(duì)象自身,即this指針。JNIEnv是JNI核心數(shù)據(jù)庫之一,地位非常崇高,所有對(duì)JNI的調(diào)用都要通過此結(jié)構(gòu)體。請(qǐng)注意:jni.h文件必須被包含,該文件定義了JNI所有的函數(shù)聲明和數(shù)據(jù)類型。生成本地庫的名字,必須與System.loadLibrary("Hello World“);待裝載庫的名字相同。-MD:保證與Win32多線程C庫連接(win分為靜態(tài)、動(dòng)態(tài)、動(dòng)態(tài)多線程。。。C庫)-LD:生成動(dòng)態(tài)鏈接庫
7、一對(duì)一映射和shared stubs的對(duì)比
shared stubs的主要優(yōu)點(diǎn)是程序員不必在本地代碼中寫一大堆的stub函數(shù),一對(duì)一映射的優(yōu)點(diǎn)是高效,因?yàn)樗恍枰嗟母郊拥臄?shù)據(jù)類型轉(zhuǎn)換。