歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android HAL實例解析

一、概述

    本文希望通過分析台灣的Jollen的mokoid 工程代碼,和在s5pc100平台上實現過程種遇到的問題,解析Andorid HAL的開發方法。     

二、HAL介紹

    現有HAL架構由Patrick Brady (Google) 在2008 Google  I/O演講中提出的,如下圖。

 

 

    Android的HAL是為了保護一些硬件提供商的知識產權而提出的,是為了避開linux的GPL束縛。思路是把控制硬件的動作都放到了Android HAL中,而linux driver僅僅完成一些簡單的數據交互作用,甚至把硬件寄存器空間直接映射到user space。而Android是基於Aparch的license,因此硬件廠商可以只提供二進制代碼,所以說Android只是一個開放的平台,並不是一個開源的平台。也許也正是因為Android不遵從GPL,所以Greg Kroah-Hartman才在2.6.33內核將Andorid驅動從linux中刪除。GPL和硬件廠商目前還是有著無法彌合的裂痕。Android想要把這個問題處理好也是不容易的。

    總結下來,Android HAL存在的原因主要有:

    1. 並不是所有的硬件設備都有標准的linux kernel的接口

    2. KERNEL DRIVER涉及到GPL的版權。某些設備制造商並不原因公開硬件驅動,所以才去用HAL方    式繞過GPL。

    3. 針對某些硬件,An有一些特殊的需求 

三、HAL內容

1、HAL 主要的儲存於以下目錄:

(注意:HAL在其它目錄下也可以正常編譯)

l  libhardware_legacy/ - 舊的架構、采取鏈接庫模塊的觀念進行

l  libhardware/ - 新架構、調整為 HAL stub 的觀念

l  ril/ - Radio Interface Layer

l  msm7k  QUAL平台相關

    主要包含以下一些模塊:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Overlay等。

2、兩種 HAL 架構比較

    目前存在兩種HAL架構,位於libhardware_legacy目錄下的“舊HAL架構”和位於libhardware目錄下的“新HAL架構”。兩種框架如下圖所示。

                   圖3.1   舊HAL架構                             圖3.2  新HAL架構

 

      libhardware_legacy 是將 *.so 文件當作shared library來使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通過直接函數調用的方式,來操作驅動程序。當然,應用程序也可以不需要通過 JNI 的方式進行,直接加載 *.so (dlopen)的做法調用*.so 裡的符號(symbol)也是一種方式。總而言之是沒有經過封裝,上層可以直接操作硬件。

    現在的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,可以認為Android定義了HAL層結構框架,通過幾個接口訪問硬件從而統一了調用方式。

    下面結合實例來分析HAL編程方法。 

四、mokoid 工程代碼下載與結構分析

1、mokid項目概述

    modkoid工程提供了一個LedTest示例程序,是台灣的Jollen用於培訓的。對於理解android層次結構、Hal編程方法都非常有意義。

2、下載方法

    #svn checkout http://mokoid.googlecode.com/svn/trunk/mokoid-read-only

3、結構分析

|-- Android.mk  

|-- apps      //兩種應用測試方法

|   |-- Android.mk

|   |-- LedClient    //直接調用service來調用jni

|   |   |-- AndroidManifest.xml

|   |   |-- Android.mk

|   |   `-- src

|   |       `-- com

|   |           `-- mokoid

|   |               `-- LedClient

|   |                   `-- LedClient.java     //第1種方式應用程序實現代碼

|   `-- LedTest        //通過manager來調用jni

|       |-- AndroidManifest.xml

|       |-- Android.mk

|       `-- src

|           `-- com

|               `-- mokoid

|                   `-- LedTest

|                       |-- LedSystemServer.java  //開啟了一個後台service,下文會有解釋

|                       `-- LedTest.java    //第2種方式應用程序實現代碼

|-- dma6410xp   //這個目錄可以不要

|   |-- AndroidBoard.mk

|   |-- AndroidProducts.mk

|   |-- BoardConfig.mk

|   |-- dma6410xp.mk

|   |-- init.dma6410xp.rc

|   |-- init.goldfish.sh

|   `-- init.rc

|-- frameworks     //框架代碼

|   |-- Android.mk

|   `-- base

|       |-- Android.mk

|       |-- core

|       |   `-- java

|       |       `-- mokoid

|       |           `-- hardware

|       |               |-- ILedService.aidl

|       |               `-- LedManager.java     //實現了Manager,給第2種方法用

|       `-- service  

|           |-- Android.mk

|           |-- com.mokoid.server.xml

|           |-- java

|           |   `-- com

|           |       `-- mokoid

|           |           `-- server

|           |               `-- LedService.java    //Framework service代碼

|           `-- jni

|               |-- Android.mk

|               `-- com_mokoid_server_LedService.cpp  //jni代碼

|-- hardware

|   |-- Android.mk

|   |-- libled

|   |   |-- Android.mk

|   |   `-- libled.c

|   `-- modules

|       |-- Android.mk

|       |-- include

|       |   `-- mokoid

|       |       `-- led.h

|       `-- led

|           |-- Android.mk

|           `-- led.c       //led stub 硬件控制代碼

`-- README.txt

 

 

    Android的HAL的實現需要通過JNI(Java Native Interface),JNI簡單來說就是java程序可以調用C/C++寫的動態鏈接庫,這樣的話,HAL可以使用C/C++語言編寫,效率更高。在Android下訪問HAL大致有以下兩種方式:

 

  (1)Android的app可以直接通過service調用.so格式的jni

 

 

 

 

 

 

(2)經過Manager調用service

 

     上面兩種方法應該說是各有優缺點,第一種方法簡單高效,但不正規。第二種方法實現起來比較復雜,但更符合目前的Android框架。第二種方法中,LegManager和LedService(java)在兩個進程中,需要通過進程通訊的方式來通訊。

     mokoid工程中實現了上述兩種方法。下面將詳細介紹這兩種方法的實現原理。

Copyright © Linux教程網 All Rights Reserved