Android HAL硬件抽象層與硬件系統架構

背景

    近幾年是互聯網高速發展的幾年,孕育出瞭如谷歌、阿里巴巴等許多超級互聯網公司,隨着互聯網的發展已經觸到了天花板,一個比互聯網更大的市場即將打開,那就是物聯網(Internet of Things)。IOT就是將現實世界中的物體連到互聯網上,使得物與物、人與物可以很方便的互相溝通,將是下一個規模更大網絡發展機遇的風口,是一個高科技公司搶佔技術高地和風口,谷歌近日發佈了第一代物聯網平臺操作系統Android Things。華爲也推出了IOT操作系統LiteOS。

    說到IOT,我們最多的是理解成智能硬件,萬物互聯;確實,IOT系統的每個節點都是不同的智能硬件,都是不同的網絡智能終端設備。咱們豐巢快遞智能櫃也在某種程度上說也屬於IOT設備。所以開發基於Android系統的豐巢智能櫃,高鐵寄存櫃;我們有必要去搞懂Android的硬件系統和HAL層,正好我以前有過Android系統開發和HAL驅動開發的經驗,和大家分享討論下硬件相關知識。

整體架構

在這裏插入圖片描述

    如圖,Android系統的整個架構由五層結構組成:

  • 應用層(Applications):這一層主要用於手機應用的安裝,如系統自帶聯繫人、短信等程序,或是第三方應用程序;
  • 應用框架層(Application framework):這一層主要提供構建應用程序時可能用到的各種API,Android自帶的一些核心應用就是使用這些API完成的,開發者也可通過使用API來構建自己的應用程序;
  • 系統運行庫層(Libraries And Runtimes):這一層通過一些C/C++庫(so庫)來爲Android系統提供了主要的特性支持。如SQLite庫提供了數據庫支持,OpenGL ES庫提供了3D繪圖支持,Webkit庫提供了瀏覽器內核支持等;
  • 硬件抽象層(hardware abstraction layer):安卓驅動硬件的方式與Linux不盡相同。傳統Linux的驅動完全存活於內核空間。硬件抽象層(HAL, Hardware Abstraction Layer),把一部分驅動功能放到HAL層中。安卓爲什麼費盡麻煩增加一個HAL呢?爲了保護源代碼。Linux內核採用了GPL協議,所以硬件生產商想要支持Linux系統,必須遵照GPL協議公開硬件驅動的源代碼。但這些源代碼中包含有許多硬件的設計信息,牽涉到硬件生產商的核心利益。而增加了HAL層之後,硬件廠商就不需要開放所有的驅動代碼了。
  • Linux內核層(Linux Kernel):Android系統基於Linux2.6內核,這一層爲Android設備各種硬件提供了底層驅動,如顯示驅動、音頻驅動、照相機驅動、藍牙驅動、Wi-Fi驅動、電源管理等;

    Android HAL層不是Android一直都存在的,是從android4.0.3開始才加入的。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. 針對某些硬件,Android有一些特殊的需求

硬件系統架構介紹

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

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

    現在的 libhardware HAL架構,就有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層結構框架,通過幾個接口訪問硬件從而統一了調用方式。

硬件架構源碼分析

    下面我們從普通的振動器硬件的控制vibrate使用開始,從振動器服務的獲取getSystemService方法,然後到硬件服務的調用,然後通過HAL硬件抽象層打開硬件驅動節點文件讀寫等操作,然後到Linux內核態驅動程序,以及處理器芯片引腳的控制與芯片時序驅動,一步一步講解Android的新的硬件系統架構HAL架構是怎麼進行硬件設備調度和控制的…
         [外鏈圖片轉存失敗]

APP層

Android應用層對振動器的調用形式一般是,通過獲取到Vibrator實例後,通過實例方法vibrate來控制震動器的振動操作

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);

通過源碼跟蹤,通常調getSystemService調的是ContextImpl裏面的getSystemService方法

framework層

位置:frameworks\base\core\java\android\app\ContextImpl.java

@Override
public Object getSystemService(String name) {
    ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
    return fetcher == null ? null : fetcher.getService(this);
}

可以看出是從SYSTEM_SERVICE_MAP集合裏面通過那麼作爲key進行取出ServiceFetcher,然後getService獲取到服務的實例。那SYSTEM_SERVICE_MAP集合裏面存的服務實例是從哪裏來呢?

private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
            new HashMap<String, ServiceFetcher>();

private static void registerService(String serviceName, ServiceFetcher fetcher) {
        if (!(fetcher instanceof StaticServiceFetcher)) {
            fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
        }
        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}

private static void registerService(String serviceName, ServiceFetcher fetcher) {
        if (!(fetcher instanceof StaticServiceFetcher)) {
            fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
        }
        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
    }

static {
		...
        registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return new SystemVibrator(ctx);
                }});
		...

實際上SYSTEM_SERVICE_MAP裏面添加的服務Fetcher是通過類靜態塊進行registerService註冊進去的。接下來我們看看SystemVibrator類的實現

位置:frameworks\base\core\java\android\os\SystemVibrator.java


public class SystemVibrator extends Vibrator {
    private static final String TAG = "Vibrator";

    private final IVibratorService mService;
    private final Binder mToken = new Binder();

    public SystemVibrator() {
        mService = IVibratorService.Stub.asInterface(
                ServiceManager.getService("vibrator"));
    }

    public SystemVibrator(Context context) {
        super(context);
        mService = IVibratorService.Stub.asInterface(
                ServiceManager.getService("vibrator"));
    }

    @Override
    public boolean hasVibrator() {
          ...
          return mService.hasVibrator();

    }

    /**
     * @hide
     */
    @Override
    public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
        ...
        mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken);

    }

   ...

    @Override
    public void cancel() {
        ...
        mService.cancelVibrate(mToken);
    }
}

SystemVibrator類相當於一個代理類,主要是通過Binder通信拿到IVibratorService,然後去遠程調用對應的方法
,我們看到遠程的Service IBinder是怎麼獲取過來的,看看ServiceManager.getService(“vibrator”)查找ServiceManager的getService方法的具體實現

位置:frameworks\base\core\java\android\os\ServiceManager.java

public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

    ....
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }


    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

    ....

}

ServiceManager.getService(“vibrator”)獲取到的IBinder是從sCache HashMap裏面獲取到的,我們查查是怎麼添加進去的。

位置:frameworks\base\services\java\com\android\server\SystemServer.java

public static void main(String[] args) {

        new SystemServer().run();
}


//run
private void run() {
	  ...
    //開始啓動服務
	  startBootstrapServices();
    //開啓核心服務
    startCoreServices();
    //開啓另外一些服務
    startOtherServices();
	  ...
}
//startOtherServices
private void startOtherServices() {

	  ...
	  Slog.i(TAG, "Vibrator Service");
    vibrator = new VibratorService(context);
    ServiceManager.addService("vibrator", vibrator);
}

系統在初始化時候,SystemServer.main()方法,然後調用run調用了startOtherServices()這時候可以看出其實是在SystemServer註冊了VibratorService服務,然後加入了ServiceManager裏面去管理.想知道Android系統啓動流程,可以看看我的另外一篇博客:https://blog.csdn.net/zgkxzx/article/details/88623498

位置:frameworks\base\services\core\java\com\android\server\VibratorService.java

public class VibratorService extends IVibratorService.Stub
        implements InputManager.InputDeviceListener {

	native static boolean vibratorExists();
    native static void vibratorOn(long milliseconds);
    native static void vibratorOff();

		...
	@Override // Binder call
  public void vibrate(int uid, String opPkg, long milliseconds, int usageHint,
            IBinder token) {
        ...
        startVibrationLocked(vib);

    }
	 //
	 private void startVibrationLocked(final Vibration vib) {
            ...
            //開啓VibrateThread線程
            mThread = new VibrateThread(vib);
            mThread.start();
        }
  }

	private class VibrateThread extends Thread {
		public void run() {
			...
			VibratorService.this.doVibratorOn(duration, uid, usageHint);
		}
	}
	private void doVibratorOn(long millis, int uid, int usageHint) {
			...
      //調用JNI Native本地方法
        vibratorOn(millis);

      }
    }
  }

VibratorService服務通過創建了VibrateThread線程,然後去調用Native本地端的振動器的接口vibratorOn方法

HAL層

位置:frameworks\base\services\core\jni\com_android_server_VibratorService.cpp

#include <hardware_legacy/vibrator.h>

#include <stdio.h>

namespace android
{

static hw_module_t *gVibraModule = NULL;
static vibrator_device_t *gVibraDevice = NULL;

static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
{
    ...
    int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);

}



static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
     ...
    int err = gVibraDevice->vibrator_on(gVibraDevice, timeout_ms);

}

static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{
    ...
    int err = gVibraDevice->vibrator_off(gVibraDevice);
}

static const JNINativeMethod method_table[] = {
    { "vibratorExists", "()Z", (void*)vibratorExists },
    { "vibratorInit", "()V", (void*)vibratorInit },
    { "vibratorOn", "(J)V", (void*)vibratorOn },
    { "vibratorOff", "()V", (void*)vibratorOff }
};

int register_android_server_VibratorService(JNIEnv *env)
{
    return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
            method_table, NELEM(method_table));
}

};

com_android_server_VibratorService.cpp 這個典型的HAL抽象層,通過hw_get_module獲取到hw_module_t硬件模塊描述結構體對象,然後對改對象進行vibratorOn或vibratorOff調用控制。

位置:hardware/libhardware/modules/vibrator/vibrator.c

#include <hardware/vibrator.h>
#include <hardware/hardware.h>


static const char THE_DEVICE[] = "/sys/class/timed_output/vibrator/enable";


static int sendit(unsigned int timeout_ms)
{
    int to_write, written, ret, fd;

    ...
    //獲取到驅動設備節點的文件描述符
    fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));

    //對設備文件進行寫操作
    written = TEMP_FAILURE_RETRY(write(fd, value, to_write));

    //關閉文件
    close(fd);

    return ret;
}

static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
{
    return sendit(timeout_ms);
}

static int vibra_off(vibrator_device_t* vibradev __unused)
{
    return sendit(0);
}

static int vibra_close(hw_device_t *device)
{
    free(device);
    return 0;
}

static int vibra_open(const hw_module_t* module, const char* id __unused,
                      hw_device_t** device __unused) {


    vibradev->common.tag = HARDWARE_DEVICE_TAG;
    vibradev->common.module = (hw_module_t *) module;
    vibradev->common.version = HARDWARE_DEVICE_API_VERSION(1,0);
    vibradev->common.close = vibra_close;

    vibradev->vibrator_on = vibra_on;
    vibradev->vibrator_off = vibra_off;

    *device = (hw_device_t *) vibradev;

    return 0;
}


static struct hw_module_methods_t vibrator_module_methods = {
    .open = vibra_open,
};

struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .module_api_version = VIBRATOR_API_VERSION,
    .hal_api_version = HARDWARE_HAL_API_VERSION,
    .id = VIBRATOR_HARDWARE_MODULE_ID,
    .name = "Default vibrator HAL",
    .author = "The Android Open Source Project",
    .methods = &vibrator_module_methods,
};

這裏是com_android_server_VibratorService.cpp文件的頭文件,主要是HAL的接口描述映射關係,以及Linux用戶層的驅動文件打開與控制,vibra_on與vibra_off實際上最終能調用的是sendit函數,通過open方法打開驅動節點/sys/class/timed_output/vibrator/enable進行寫操作,來實現振動器Vibrator硬件設備的控制。

Linux驅動層

位置:drivers/misc/misc_sysfs.c

#include <linux/kernel.h>
...
#include <mach/gpio.h>

 // vibrator 對應的GPIO
 #define  VIBRATOR_POWER_PORT (EXYNOS4_GPD(1))

 static unsigned char vibrator_status = 0;


 static void vibrate_init(void)
 {
     int ret;

     ret = gpio_request(VIBRATOR_POWER_PORT, "GPX1");
     if(ret)
        printk("open  vibrator device fail\n");
      //VIBRATOR_POWER_PORT引腳加入上拉配置
     s3c_gpio_setpull(VIBRATOR_POWER_PORT, S3C_GPIO_PULL_UP);
     //VIBRATOR_POWER_PORT引腳輸出低電平
     gpio_direction_output(VIBRATOR_POWER_PORT, vibrator_status);
 }


 //讀函數
 static ssize_t show_vibrator_onoff (struct device *dev, struct device_attribute *attr, char *buf)
 {
     return    vibrator_status;
 }
 //寫函數
 static ssize_t set_vibrator_onoff (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
      unsigned int    vibrator_status;

     if(!(sscanf(buf, "%u\n", &vibrator_status)))     
        return    -EINVAL;
     if(!vibrator_status )    
     {
         vibrator_status = 0;
         //VIBRATOR_POWER_PORT引腳輸出低電平
         gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW);
     } else  {
         vibrator_status = 1;
          //VIBRATOR_POWER_PORT引腳輸出高電平
         gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_HIGH);
     }

     return count;
 }

 static    ssize_t show_vibrator_onoff    (struct device *dev, struct device_attribute *attr, char *buf);
 static     ssize_t set_vibrator_onoff    (struct device *dev, struct device_attribute *attr, const char *buf, size_t count);

 static DEVICE_ATTR(vibrator_onoff, S_IRWXUGO, show_vibrator_onoff, set_vibrator_onoff);

 static struct attribute *control_sysfs_entries[] = {
     &dev_attr_vibrator_onoff.attr,
     NULL
 };

 static struct attribute_group control_sysfs_attr_group = {
     .name   = NULL,
     .attrs  = control_sysfs_entries,
 };
//探測函數,驅動框架第一個初始化的函數
 static int control_sysfs_probe(struct platform_device *pdev)    
 {
     printk("vibrator probe");
     vibrate_init();
     return    sysfs_create_group(&pdev->dev.kobj, &control_sysfs_attr_group);
 }

 staticint control_sysfs_remove(struct platform_device *pdev)    
 {
     sysfs_remove_group(&pdev->dev.kobj, &control_sysfs_attr_group);
     return    0;
 }


 static struct platform_driver control_sysfs_driver = {
     .driver = {
         .name = "misc_ctl",
         .owner = THIS_MODULE,
     },
     .probe         = control_sysfs_probe,
     .remove     = control_sysfs_remove,
 };
 // 將vibrator註冊到platform總線
 static int __init control_sysfs_init(void)
 {    
     return platform_driver_register(&control_sysfs_driver);
 }

 static void __exit control_sysfs_exit(void)
 {
    platform_driver_unregister(&control_sysfs_driver);
 }

 module_init(control_sysfs_init);
 module_exit(control_sysfs_exit);

 MODULE_DESCRIPTION("misc control driver for zgkxzx");
 MODULE_AUTHOR("other");
 MODULE_LICENSE("GPL");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章