Android系统从宏观上可以看成一个图形系统,类似于QT,迷你GUI等开源的图形用户界面系统。但是android作为手机软件包,它还具有很多的其他功能是QT、MINIGUI不具备的,比如电话、定位、WIFI、sensor、摄像头等功能。Android集成了很多开源的代码,我们只需要在Linux层做好硬件的驱动程序剩下的很多软件开发工作android都是做好了的。烧写过手机固件的都知道,android的固件大概有uboot.img、boot.img(包含ramdisk和kernel),system.img,cache.img,userdata.img等。下面是一张android启动流程图,来自网络。
其中system.img可以理解为android的本体部分。
System.img最终会挂在ramdisk的/system目录下面,其内容说明如下:
system/app 这个里面主要存放的是常规下载的应用程序,可以看到都是以APK格式结尾的文件。在这个文件夹下的程序为系统默认的组件,自己安装的软件将不会出现在这里,而是/data/文件夹中。
system/bin 这个目录下的文件都是系统的本地程序,从bin文件夹名称可以看出是binary二进制的程序,里面主要是Linux系统自带的组件。
system/etc 从文件夹名称来看保存的都是系统的配置文件,比如APN接入点设置等核心配置。
system/fonts 字体文件夹,除了标准字体和粗体、斜体外可以看到文件体积最大的可能是中文字库,或一些unicode字库。
system/framework 主要是一些核心的文件,从后缀名为jar可以看出是是系统平台框架。
system/lib lib目录中存放的主要是系统底层库,如hardware层库。
system/media 铃声音乐文件夹,除了常规的铃声外还有一些系统提示事件音
system/usr 用户文件夹,包含共享、键盘布局、时间区域文件等。
现在android编译的结果呈现在上面,从功能逻辑上android的结构是这样的:
Android的一些库的运行是依赖硬件的,但是为了让android与Linux隔离开,硬件抽象层扮演了和驱动层打交道的角色,也扮演了BSP开发应用层部分的工作。有了hardware和kernel的配合,android才能稳定的运行在目标板上。
在"/system/lib/hw"下面定义了硬件抽象层编译的动态库文件。动态库文件可以理解为厨师的各类厨具,需要就颠一下,不需要就放在那儿。那么hardware层的库文件是怎么为其他库提供支持的呢?比如android的APP应用程序现在要把一幅图显示到LCD上,就需要硬件驱动的支持,APP会通过控件调用framework层的libui库,libui库根据ID号选调hardware层的动态库"/system/lib/hw/gralloc.*.so",然后硬件抽象层再继续调用驱动层的接口/dev/fb0。
Tips:
framework层调用函数hw_get_module依次在目录/system/lib/hw和/vendor/lib/hw中检查是否存在以下四个文件:
gralloc.<ro.hardware>.so
gralloc.<ro.product.board>.so
gralloc.<ro.board.platform>.so
gralloc.<ro.arch>.so
只要其中的一个文件存在, 函数hw_get_module就会停止查找过程,并且调用另外一个函数load来将这个文件加载到内存中来。另一方面,如果在/system/lib/hw和/vendor/lib/hw中均不存这些文件,那么函数hw_get_module就会在目录/system/lib/hw中查找是否存在一个名称为gralloc.default.so的文件。
硬件抽象层调用关系(架构图):
Android硬件抽象层规定了一个框架,集中体现在某个模块的头文件的实现。以hardware\libhardware\include\hardware\gralloc.h为例(精简版):
/**
* The id of this module
*/
#define GRALLOC_HARDWARE_MODULE_ID"gralloc"
/**
* Name of the graphics device to open
*/
#defineGRALLOC_HARDWARE_FB0 "fb0"
#defineGRALLOC_HARDWARE_GPU0 "gpu0"
/**
* Every hardware module must have a datastructure named HAL_MODULE_INFO_SYM
* and the fields of this data structure mustbegin with hw_module_t
* followed by module specific information.
*/
typedef struct gralloc_module_t {
struct hw_module_t common;
int (*registerBuffer)(structgralloc_module_t const* module,
buffer_handle_t handle);
int(*unregisterBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int(*lock)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
int(*unlock)(struct gralloc_module_t const* module,
buffer_handle_t handle);
/* reserved for future use */
int (*perform)(struct gralloc_module_tconst* module,
int operation, ... );
/* reserved for future use */
void* reserved_proc[7];
}gralloc_module_t;
/**
* Every device data structure must begin withhw_device_t
* followed by module specific public methodsand attributes.
*/
typedef struct framebuffer_device_t {
struct hw_device_t common;
/* flags describing some attributes of theframebuffer */
const uint32_t flags;
/* dimensions of the framebuffer in pixels*/
const uint32_t width;
const uint32_t height;
/* frambuffer stride in pixels */
const int stride;
/* framebuffer pixel format */
const int format;
/* resolution of the framebuffer's displaypanel in pixel per inch*/
const float xdpi;
const float ydpi;
/* framebuffer's display panel refresh ratein frames per second */
const float fps;
/* min swap interval supported by thisframebuffer */
const int minSwapInterval;
/* max swap interval supported by thisframebuffer */
const int maxSwapInterval;
int reserved[8];
int (*setSwapInterval)(structframebuffer_device_t* window,
int interval);
int (*setUpdateRect)(structframebuffer_device_t* window,
int left, int top, int width, intheight);
int (*post)(struct framebuffer_device_t*dev, buffer_handle_t buffer);
int (*compositionComplete)(structframebuffer_device_t* dev);
void* reserved_proc[8];
}framebuffer_device_t;
1、 每一个hardware硬件模块都有一个ID;
2、 每一个hardware模块必须有一个继承struct hw_module_t common;的结构体;
3、 每一个hardware模块必须有一个继承struct hw_device_t common;的结构体;
structhw_module_t的继承者担负了“联络员”的任务,在/system/lib/hw下面有若干了hardware module,本地框架层通过ID找到对应的模块。
structhw_device_t的继承者承担了对驱动操作方法的包装的任务。
structhw_module_t和struct hw_device_t的内容定义在hardware\libhardware\include\hardware\hardware.h如下:
/**
* Every hardware module must have a datastructure named HAL_MODULE_INFO_SYM
* and the fields of this data structure mustbegin with hw_module_t
* followed by module specific information.
*/
typedef struct hw_module_t {
/** tag must be initialized toHARDWARE_MODULE_TAG */
uint32_t tag;
/** major version number for the module */
uint16_t version_major;
/** minor version number of the module */
uint16_t version_minor;
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module*/
const char *author;
/** Modules methods */
struct hw_module_methods_t*methods;
/** module's dso */
void* dso;
/** padding to 128 bytes, reserved forfuture use */
uint32_t reserved[32-7];
}hw_module_t;
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module,const char* id,
struct hw_device_t** device);
}hw_module_methods_t;
/**
* Every device data structure must begin withhw_device_t
* followed by module specific public methodsand attributes.
*/
typedef struct hw_device_t {
/** tag must be initialized toHARDWARE_DEVICE_TAG */
uint32_t tag;
/** version number for hw_device_t */
uint32_t version;
/** reference to the module this devicebelongs to */
struct hw_module_t* module;
/** padding reserved for future use */
uint32_t reserved[12];
/** Close this device */
int (*close)(struct hw_device_t* device);
}hw_device_t;
到此我们总结一下硬件具体的调用流程,也是hardware层的工作流程:
1、 通过ID找到硬件模块,structhw_module_t common的结构体的继承者;
2、 通过硬件模块找到hw_module_methods_t,打开操作,获得设备的hw_device_t;
3、 调用hw_device_t中的各种操作硬件的方法;
4、 调用完成,通过hw_device_t的close关闭设备。
下面是一个hardware层的helloworld的例子,目的是了解其原理,也为阅读androidHAL源码提供一个范本。
进入到在hardware/libhardware/include/hardware目录,新建hello.h文件:
#ifndefANDROID_HELLO_INTERFACE_H
#defineANDROID_HELLO_INTERFACE_H
#include<hardware/hardware.h>
__BEGIN_DECLS
/*定义模块ID*/
#defineHELLO_HARDWARE_MODULE_ID "hello"
/*硬件模块结构体*/
structhello_module_t {
struct hw_module_t common;
};
/*硬件接口结构体*/
structhello_device_t {
struct hw_device_t common;
int fd;
int (*set_val)(struct hello_device_t*dev, int val);
int (*get_val)(struct hello_device_t*dev, int* val);
};
__END_DECLS
#endif
进入到hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件
#defineLOG_TAG "HelloStub"
#include<hardware/hardware.h>
#include<hardware/hello.h>
#include<fcntl.h>
#include<errno.h>
#include<cutils/log.h>
#include<cutils/atomic.h>
/*驱动程序接口/dev/hello*/
#defineDEVICE_NAME "/dev/hello"
#defineMODULE_NAME "Hello"
/*设备打开和关闭接口*/
staticint hello_device_open(const struct hw_module_t* module, const char* name,struct hw_device_t** device);
staticint hello_device_close(struct hw_device_t* device);
/*设备访问接口*/
staticint hello_set_val(struct hello_device_t* dev, int val);
staticint hello_get_val(struct hello_device_t* dev, int* val);
/*模块方法表*/
staticstruct hw_module_methods_t hello_module_methods = {
open: hello_device_open
};
/*模块实例变量*/
structhello_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: HELLO_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: “mr shao”,
methods:&hello_module_methods,
}
};
static int hello_device_open(const structhw_module_t* module, const char* name, struct hw_device_t** device) {
structhello_device_t* dev;dev = (struct hello_device_t*)malloc(sizeof(structhello_device_t));
if(!dev){
LOGE("HelloStub: failed to alloc space");
return-EFAULT;
}
memset(dev,0, sizeof(struct hello_device_t));
dev->common.tag= HARDWARE_DEVICE_TAG;
dev->common.version= 0;
dev->common.module= (hw_module_t*)module;
dev->common.close= hello_device_close;
dev->set_val= hello_set_val;dev->get_val = hello_get_val;
if((dev->fd= open(DEVICE_NAME, O_RDWR)) == -1) {
LOGE("HelloStub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);
return-EFAULT;
}
*device= &(dev->common);
LOGI("HelloStub: open /dev/hello successfully.");
return0;
}
static int hello_device_close(structhw_device_t* device) {
structhello_device_t* hello_device = (struct hello_device_t*)device;
if(hello_device){
close(hello_device->fd);
free(hello_device);
}
return0;
}
static int hello_set_val(structhello_device_t* dev, int val) {
LOGI("HelloStub: set value %d to device.", val);
write(dev->fd,&val, sizeof(val));
return0;
}
static int hello_get_val(structhello_device_t* dev, int* val) {
if(!val){
LOGE("HelloStub: error val pointer");
return-EFAULT;
}
read(dev->fd,val, sizeof(*val));
LOGI("HelloStub: get value %d from device", *val);
return0;
}
继续在hello目录下新建Android.mk文件:
LOCAL_PATH := $(call my-dir)
include$(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH:= $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES:= hello.c
LOCAL_MODULE :=hello.default
include$(BUILD_SHARED_LIBRARY)
注意,LOCAL_MODULE的定义规则,hello后面跟有default,hello.default能够保证我们的模块总能被硬象抽象层加载到。关于Android.mk的用法请参考:
例说如何编译android模块
mmm hardware/libhardware/modules/hello
编译成功后,就可以在out/target/product/generic/system/lib/hw目录下看到hello.default.so文件了。
参考文章:
《Android板级支持与硬件相关子系统》韩超 第二章