Rockie Cheng according to the Hal lecture and code of jollen (http://www.jollen.org/blog)
Http://hi.baidu.com/aokikyon
Aokikyon@gmail.com
1 Hal Introduction
The hardware abstract layer Hardware Abstraction Layer of Android is a new concept launched by Google in response to the vendor's requirement of "do not disclose source code". Its architecture is as follows. Although Hal's current "Abstraction Level" is not enough, the current implementation is not fully in line with Hal's architecture planning, it does give us a good space to think about.
Figure 1: Android Hal Architecture Planning
This is the architecture of the android Hal proposed by Patrick Brady (Google) in "Anatomy & Physiology of an android" at Google I/O 2008. From this architecture diagram, we know that Hal aims to completely separate Android framework from Linux kernel 」. So that android does not rely too much on Linux kernel, it is a bit like "kernel independent", so that android framework development can develop without considering the driver.
In the original Android code, Hal implements the following operations:
1. libhardware_legacy/-previous implementation, using the concept of a linked library module
2. libhardware/-concepts of implementing and adjusting the new version to Hal stub
3. RIL/-radio interface layer
Before the Hal architecture is mature (that is, the planning in Figure 1), we will first make a simple analysis on the current Hal status. In addition, the Hal Implementation of Android is still scattered in different places, such as camera and WiFi. Therefore, the preceding directory does not contain all Hal program code.
2 Hal's past
Figure 2: Android hal/libhardware_legacy
In the past, libhardware_legacy is a traditional "module" approach, that is, adding *. so files are used as "Shared Library", and Hal module is used as direct function call in Runtime (JNI. The driver is operated through direct function call. Of course, the application can be directly loaded * without using JNI *. so disconnect (dlopen) Call Method *. so symbol is also a method. All in all, the upper layer can directly operate the hardware without being encapsulated.
3 Hal status
Figure 3: Android hal/libhardware
The current libhardware practice has the taste of "stub. Hal stub is a proxy concept. Although stub still exists in the form of *. So exist, Hal has hidden the *. So file. Stub provides "operations" to Hal, while runtime gets the operations of a specific module (stub) to Hal, and then callback these operation functions. In this implementation architecture of indirect function call, Hal stub becomes an "include" relationship, that is, Hal contains many stub (agents ). For runtime, you only need to specify the "type", that is, the module ID, to obtain the operation function. For the current Hal, it can be considered that android defines the Hal layer structure framework and accesses the hardware through several interfaces to unify the calling method.
4 Comparison Between hal_legacy and Hal
Hal_legacy: The old Hal is a module in the form of a shared library, which is called during compilation. Because Function
Called in the form of call, so it can be used by multiple processes, but it will be mapped to multiple process spaces, resulting in waste, at the same time, you need to consider whether the code can be securely reimported (thread safe ).
HAL: The New Hal adopts the combination of Hal module and Hal stub. Hal stub is not a share library. during compilation, the upper layer only has the function pointer to access Hal stub and does not need Hal stub. The upper layer obtains and operates Hal stub through the unified interface provided by the Hal module. The so file is only mapped to a process, and there is no repeated mapping or re-import problem.
5 Hal module Architecture
Hal Moudle has three structures:
Struct hw_module_t;
Struct hw_module_methods_t;
Struct hw_device_t;
Their Inheritance relationships include:
Figure 4: inheritance relationship of the android Hal Structure
6. Hal usage
(1) native code gets Hal stub through hw_get_module call:
Hw_get_module (led_hardware_module_id, (const hw_module_t **) & module)
(2) inherit the callback of hw_module_methods_t to open the device:
Module-> methods-> open (module,
Led_hardware_module_id, (struct hw_device_t **) device );
(3) control the device by inheriting the callback of hw_device_t:
Sleddevice-> set_on (sleddevice, LED );
Sleddevice-> set_off (sleddevice, LED );
7. Hal stub Compiling Method
(1) define your own Hal struct and write the header files led. H, hardware/hardware. h.
Struct led_module_t {
Struct hw_module_t common;
};
Struct led_control_device_t {
Struct hw_device_t common;
Int FD;/* file descriptor of LED Device */
/* Supporting control APIs go here */
INT (* set_on) (struct led_control_device_t * Dev, int32_t led );
INT (* set_off) (struct led_control_device_t * Dev, int32_t led );
};
Inheritance relationships include:
Figure 5 inheritance relationship between Hal stub and Hal Module
(2) design led. C to complete function implementation and Hal stub Registration
(2.1) led_module_methods inherits hw_module_methods_t and implements open callback.
Struct hw_module_methods_t led_module_methods = {
Open: led_device_open
};
(2.2) Use hal_module_info_sym instance led_module_t. This name cannot be modified.
Tag: It must be set to hardware_module_tag.
ID: module ID specified as Hal stub
Methods: struct hw_module_methods_t, which is the "method" defined by Hal 」
Const struct led_module_t hal_module_info_sym = {
Common :{
Tag: hardware_module_tag,
Version_major: 1,
Version_minor: 0,
ID: led_hardware_module_id,
Name: "sample led stub ",
Author: "The mokoid open source project ",
Methods: & led_module_methods,
}
/* Supporting APIs go here .*/
};
(2.3) open is a required callback API. It applies for struct space, fills in information, registers specific operation API interfaces, and opens the Linux driver.
As there are multiple inheritance relationships, you only need to apply for a space for the Child structure hw_device_t object.
Int led_device_open (const struct hw_module_t * module, const char * Name, struct hw_device_t ** device)
{
Struct led_control_device_t * dev;
Dev = (struct led_control_device_t *) malloc (sizeof (* Dev ));
Memset (Dev, 0, sizeof (* Dev ));
Dev-> common. Tag = hardware_device_tag;
Dev-> common. Version = 0;
Dev-> common. module = module;
Dev-> common. Close = led_device_close;
Dev-> set_on = led_on;
Dev-> set_off = led_off;
* Device = & Dev-> common;
/*
* Initialize led hardware here.
*/
Dev-> FD = open (led_device, o_rdonly );
If (Dev-> FD <0)
Return-1;
Led_off (Dev, led_c608 );
Led_off (Dev, led_c609 );
Success:
Return 0;
}
(2.4) Fill in the specific API operation code
Int led_on (struct led_control_device_t * Dev, int32_t led)
{
Int FD;
Logi ("led stub: Set % d on.", LED );
FD = Dev-> FD;
Switch (LED ){
Case led_c608:
IOCTL (FD, 1, & LED );
Break;
Case led_c609:
IOCTL (FD, 1, & LED );
Break;
Default:
Return-1;
}
Return 0;
}
Int led_off (struct led_control_device_t * Dev, int32_t led)
{
Int FD;
Logi ("led stub: Set % d off.", LED );
FD = Dev-> FD;
Switch (LED ){
Case led_c608:
IOCTL (FD, 2, & LED );
Break;
Case led_c609:
IOCTL (FD, 2, & LED );
Break;
Default:
Return-1;
}
Return 0;
}