背景
近幾年是互聯網高速發展的幾年,孕育出瞭如谷歌、阿里巴巴等許多超級互聯網公司,隨着互聯網的發展已經觸到了天花板,一個比互聯網更大的市場即將打開,那就是物聯網(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");