Android 的 HAL(硬體抽像層)是 Google 因應廠商「希望不公開源碼」的要求下,所推出的新觀念,其架構如下圖。雖然 HAL 現在的「抽象程度」還不足,現階段實作還不是全面符合 HAL 的架構規劃,不過也確實給了我們很好的思考空間。
圖1:Android HAL 架構規劃
這是 Patrick Brady (Google) 在2008 Google I/O 所發表的演講「Anatomy & Physiology of an Android」中,所提出的 Android HAL 架構圖。從這張架構圖我們知道,HAL 的目的是為了把 Android framework 與 Linux kernel 完整「隔開」。讓 Android 不至過度依賴 Linux kernel,有點像是「kernel independent」的意思,讓 Android framework 的開發能在不考量驅動程式的前提下進行發展。
在 Android 原始碼裡,HAL 主要的實作儲存於以下目錄:
1. libhardware_legacy/ - 過去的實作、採取程式庫模組的觀念進行
2. libhardware/ - 新版的實作、調整為 HAL stub 的觀念
3. ril/ - Radio Interface Layer
在 HAL 的架構實作成熟前(即圖1的規劃),我們先就目前 HAL 現況做一個簡單的分析。另外,目前 Android 的 HAL 實作,仍舊散佈在不同的地方,例如 Camera、WiFi 等,因此上述的目錄並不包含所有的 HAL 程式碼。
HAL 的過去
圖2:Android HAL / libhardware_legacy
過去的 libhardware_legacy 作法,比較是傳統的「module」方式,也就是將 *.so 檔案當做「shared library」來使用,在 runtime(JNI 部份)以 direct function call 使用 HAL module。透過直接函數呼叫的方式,來操作驅動程式。
當然,應用程式也可以不需要透過 JNI 的方式進行,直接以載入 *.so 檔(dlopen)的做法呼叫 *.so 裡的符號(symbol)也是一種方式。
HAL 的現實狀況
圖3:Android HAL / libhardware
現在的 libhardware 作法,就有「stub」的味道了。HAL stub 是一種代理人(proxy)的概念,stub 雖然仍是以 *.so 檔的形式存在,但 HAL 已經將 *.so 檔隱藏起來了。Stub 向 HAL「提供」操作函數(operations),而 runtime 則是向 HAL 取得特定模組(stub)的 operations,再 callback 這些操作函數。這種以 indirect function call 的實作架構,讓 HAL stub 變成是一種「包含」關係,即 HAL 裡包含了許許多多的 stub(代理人)。Runtime 只要說明「類型」,即 module ID,就可以取得操作函數。
HAL 的未來發展?
新的 HAL 做法,傾向全面採用 JNI 的方式進行。也就是,在 Android 的架構中,修改 Android runtime 實作(即「Core Library」),在取得 HAL 模組的 operations 後再做 callback 操作。將 HAL 模組完全放在 HAL 裡面。