Knowledge about Android hal

Source: Internet
Author: User

Transfer

Http://blog.csdn.net/k229650014/article/details/5801397

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 (agent ). 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;
}

 

 

 

 

<! --/* Font Definitions */@ font-face {font-family:; panose-1: 2 1 6 0 3 1 1 1 1 1; MSO-font-alt: simsun; MSO-font-charset: 134; MSO-generic-font-family: auto; MSO-font-pitch: variable; MSO-font-Signature: 3 135135232 16 0 262145 0 ;} @ font-face {font-family: "/@ ";
Panose-1: 2 1 6 0 3 1 1 1 1 1; MSO-font-charset: 134; MSO-generic-font-family: auto; MSO-font-pitch: variable; MSO-font-Signature: 3 135135232 16 0 262145 0;}/* style definitions */P. msonormal, Li. msonormal, Div. msonormal {MSO-style-parent: ""; margin: 0 cm; margin-bottom :. 0001pt;
Text-align: justify; text-justify: Inter-ideograph; MSO-pagination: none; font-size: 10.5pt; MSO-bidi-font-size: 12.0pt; font-family: "Times New Roman"; MSO-Fareast-font-family:; MSO-font-kerning: 1.0pt ;} /* Page Definitions */@ page {MSO-page-border-Surround-header: No;
MSO-page-border-Surround-footer: No;} @ page Section1 {size: 595.3pt 841.9pt; margin: 72.0pt 90.0pt 72.0pt 90.0pt; MSO-header-margin: 42.55pt; MSO-footer-margin: 49.6pt; MSO-paper-Source: 0; Layout-grid: 15.6pt;} Div. section1 {page: Section1;} -->

How Android Hal is called

For Android hardware calls, Google recommends calling using Hal. For the andriod Hal writing method, refer to the templates of several modules under the hardware directory in the android source code.

When you look at Hal's compiling method, you will find that the entire module does not seem to have a portal. Generally, a module has an entry. For example, an application has a main function, which can be loaded and executed for the loader. The DLL file has a dllmain, and for the dynamic link library we write ourselves, we can call any exported symbols in the library.

The problem is that Hal in Android is quite universal and requires upper-layer functions to load and call it, how does the Hal loader of Android implement universal calls to different hardware modules?

Check the android source code with this question and you will find that Hal is called in Android through hw_get_module.

Int hw_get_module (const char * ID, const struct hw_module_t ** module );

This is the prototype of the function. The ID specifies the hardware ID, which is a string. For example, the sensor ID is

# Define sensors_hardware_module_id "sensors". If the corresponding hw_module_t struct is found, the pointer is placed into * module. Let's take a look at its implementation ....

/* Loop through the configuration variants looking for a module */

For (I = 0; I

If (I

// Obtain key values such as Ro. Hardware/Ro. Product. Board/Ro. Board. Platform/Ro. Arch.

If (property_get (variant_keys [I], prop, null) = 0 ){

Continue;

}

Snprintf (path, sizeof (PATH), "% S/% S. % S. So ",

Hal_library_path, ID, Prop );

// If the Development Board is called mmdroid, the path here is system/lib/HW/sensor. mmdroid. So

} Else {

Snprintf (path, sizeof (PATH), "% S/% S. Default. So ",

Hal_library_path, ID );// By default,/system/lib/HW/sensor. Default. So will be loaded.

 

}

If (access (path, r_ OK )){

Continue;

}

/* We found a library matching this ID/variant */

Break;

}

Status =-enoent;

If (I

/* Load the module, if this fails, we're doomed, And We shoshould not try

* To load a different variant .*/

Status = load (ID, path, module );// Call the load function to open the dynamic link library

}

 

 

After obtaining the path of the Dynamic Link Library, the load function will be called to open it. Next, it will be opened.

 

Mystery in Load

Static int load (const char * ID,

Const char * path,

Const struct hw_module_t ** phmi)

{

Int status;

Void * handle;

Struct hw_module_t * HMI;

 

/*

* Load the symbols resolving undefined symbols before

* Dlopen returns. Since rtld_global is not or 'd in

* Rtld_now the external symbols will not be global

*/

Handle = dlopen (path, rtld_now );// Open the dynamic library

If (handle = NULL ){

Char const * err_str = dlerror ();

LogE ("load: module = % s/n % s", path, err_str? Err_str: "unknown ");

Status =-einval;

Goto done;

}

 

/* Get the address of the struct hal_module_info .*/

Const char * sym = hal_module_info_sym_as_str;// Defined as "HMI"

HMI = (struct hw_module_t *) dlsym (handle, sym );//Search for the "HMI" Export symbol and obtain its address

If (HMI = NULL ){

LogE ("load: Couldn't find symbol % s", sym );

Status =-einval;

Goto done;

}

 

/* Check that the ID matches */

//The hw_module_t structure is found !!!

If (strcmp (ID, HMI-> ID )! = 0 ){

LogE ("load: Id = % s! = HMI-> id = % s ", ID, HMI-> ID );

Status =-einval;

Goto done;

}

 

HMI-> DSO = handle;

 

/* Success */

Status = 0;

 

Done:

If (status! = 0 ){

HMI = NULL;

If (handle! = NULL ){

Dlclose (handle );

Handle = NULL;

}

} Else {

Logv ("loaded Hal id = % s Path = % s HMI = % P handle = % P ",

ID, path, * phmi, handle );

}

//Triumph

* Phmi = HMI;

 

Return status;

}

From the code above, we will find a very strange macro hal_module_info_sym_as_str, which is directly defined as # define hal_module_info_sym_as_str "HMI ", why can we find the hw_module_t struct in the dynamic link library based on it? Let's take a look at the so corresponding to the hal we use. In Linux, we can use readelf XX. So-s to view it.

Symbol table '. dynsym' contains 28 entries:

Num: value size type bind vis ndx name

0: 00000000 0 notype local default und

1: 00000594 0 section local default 7

2: 00001104 0 section local default 13

3: 00000000 0 func global default und IOCTL

4: 00000000 0 func global default und strerror

5: 00000b84 0 notype global default ABS _ exidx_end

6: 00000000 0 object global default und _ stack_chk_guard

7: 00000000 0 func global default und _ aeabi_unwind_cpp_pr0

8: 00000000 0 func global default und _ errno

9: 00001188 0 notype global default ABS _ bss_end __

10: 00000000 0 func global default und malloc

11: 00001188 0 notype global default ABS _ bss_start __

12: 00000000 0 func global default und _ android_log_print

13: 00000b3a 0 notype global default ABS _ exidx_start

14: 00000000 0 func global default und _ stack_chk_fail

15: 00001188 0 notype global default ABS _ bss_end __

16: 00001188 0 notype global default ABS _ bss_start

17: 00000000 0 func global default und memset

18: 00000000 0 func global default und _ aeabi_uidiv

19: 00001188 0 notype global default ABS _ end __

20: 00001188 0 notype global default ABS _ edata

21: 00001188 0 notype global default ABS _ end

22: 00000000 0 func global default und open

23: 00080000 0 notype global default ABS _ Stack

24: 00001104 128 object global default 13 HMI

25: 00001104 0 notype global default 13 _ data_start

26: 00000000 0 func global default und close

27: 00000000 0 func global default und free

From the above, there are 24th symbols named "HMI", corresponding to the hw_module_t struct. Then compare the Hal code.

/*

* The copybit Module

*/

Struct copybit_module_t hal_module_info_sym = {

Common :{

Tag: hardware_module_tag,

Version_major: 1,

Version_minor: 0,

ID: copybit_hardware_module_id,

Name: "qct msm7k copybit module ",

Author: "Google, Inc .",

Methods: & copybit_module_methods

}

};

A copybit_module_t struct named hal_module_info_sym is defined here. The common member is of the hw_module_t type. Note that the hal_module_info_sym variable must be named, so that the compiler will change the exported symbol of this struct to "HMI" so that this struct can be found by the dlsym function!

In summary, we know that the andriod Hal module also has a common entry address, which is the hal_module_info_sym variable, we can access all methods in the Hal module that require external access.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.