The android HAL (Hardware abstract layer) is designed to protect the intellectual property of some hardware providers in order to avoid the GPL of Linux. The idea is to put the control hardware action into the Android HAL, and Linux driver just do some simple data interaction, and even the hardware register space directly mapped to user space. And Android is based on Aparch license, so hardware vendors can only provide binary code, so that Android is only an open platform, not an open source platform.
To summarize, the main reasons for Android HAL exist are:
- Not all hardware devices have standard Linux kernel interfaces
- KERNEL driver relates to the copyright of the GPL. Some device manufacturers do not have the reason to expose hardware drivers, so they use HAL to bypass the GPL.
- For some hardware, Android has some special needs.
- Different platform vendors can implement their own HAL with the HAL invocation interface, without affecting the upper level of the caller, thus reducing the coupling between the modules, so that the Platform developers only concerned about the HAL itself implementation can.
Is where Hal is located in the Android system:
As you can see from this diagram, Hal isolates the kernel from the framework so that the upper layer can be developed without relying on kernel and driver implementations. In Android source code, HAL is roughly in the following locations:
- libhardware_legacy/-The old schema, taking the mode of the link library module.
- Libhardware/-New architecture, tuning to the concept of HAL stub.
- ril/-Radio Interface Layer.
- msm7k qual platform related.
Mainly includes the following modules: Gps, Vibrator, Wifi, Copybit, Audio, Camera, Lights, Ril, Gralloc and so on.
2. Two ways to implement HAL
The old HAL is implemented separately with the new HAL implementation block diagram:
Libhardware_legacy is to use the *.so file as a shared library, using the HAL module in the Runtime (JNI section) with direct function call. The driver is manipulated by means of a direct function call. Of course, applications can also be done without JNI, and it is also a way to directly load *.so (Dlopen) to invoke symbols (symbol) in *.so. All in all, without encapsulation, the upper layer can operate the hardware directly.
Now the Libhardware practice, there is "stub" taste. The HAL stub is a proxy concept, and the stub is still in the form of a *.so file, but Hal has hidden the *.so. The stub provides an "action function (operations) to the hal", and the runtime is the operations that obtains the specific module (stub) from the HAL, and then callback these operation functions. This implementation of the indirect function call makes the HAL stub a "containment" relationship, that is, the HAL contains many stubs (proxies). Runtime as long as the "type", that is, the module ID, you can get the operation function. For the current HAL, it can be assumed that Android defines the HAL layer structure framework and accesses the hardware through several interfaces to unify the calling method.
The pros and cons of these two implementations can be seen in the following ways:
The HAL of the Hal_legacy mode is a module, in the form of a shared library, that is called at compile time. Because it is called as function call, it can be used by multiple processes, but it is mapping into multiple process spaces, resulting in waste and the question of whether the code can be safely re-entered (thread safe). While the new HAL uses the HAL module and Hal stub combinations, the HAL stub is not a share library, and the upper layer only has a function pointer that accesses the HAL stub, and does not require a HAL stub. The upper layer gets and operates from the unified interface provided by the HAL module the HAL Stub,so file is only mapping to a process, and there is no duplicate mapping and re-entry issues.
3. Structure and writing method of Hal Module
The HAL module consists of two main structures:
The struct hw_module_t-represents an abstract hardware module that contains some basic information about the hardware module, such as the version number, the developer, and a member function structure.
struct hw_module_methods_t, which has only one open function pointer for opening an abstract hardware device hw_device_t.
struct hw_device_t-represents an abstract hardware device that contains a version number, a close function pointer that shuts down the hardware, and a pointer to the structure of the hw_module_t.
These two structures are defined in hardware/libhardware/include/hardware/hardware.h, and the first member variable must be the two structures to achieve similar c+ when implementing their own HW module and HW device structure. + The purpose of the inheritance.
The definitions of these two structures are as follows:
typedef struct HW_MODULE_T {/** tag must is initialized to Hardware_module_tag */uint32_t tag; /** * The API version of the implemented module. The module owner is * Responsible for updating the version when a module interface have * changed. * * The derived modules such as Gralloc and audio own and manage this field. * The module user must interpret the version field to decide whether or * not to inter-operate with the supplied modul E implementation. * For example, Surfaceflinger are responsible for making sure that * it knows what to manage different versions of the G Ralloc-module API, * and Audioflinger must know how to does the same for Audio-module API. * * The module API version should include a major and a minor component. * For example, version 1.0 could is represented as 0x0100. This format * implies that versions 0x0100-0x01ff is all api-compatible. * In the future, Libhardware'll expose a Hw_get_modulE_version () * (or equivalent) function that would take minimum/maximum supported * versions as arguments and would Be able to reject modules with * versions outside of the supplied range. * * uint16_t module_api_version; #define VERSION_MAJOR module_api_version/** * Version_major/version_minor define S is supplied here for temporary * source code compatibility. They'll is removed in the next version. * All clients must convert to the new version format. *//** * The API version of the HAL module interface. This was meant to * version the hw_module_t, hw_module_methods_t, and hw_device_t * structures and definitions. * * The HAL interface owns this field. Module Users/implementations * must not rely in this value for version information. * * Presently, 0 is the only valid value. */uint16_t hal_api_version; #define Version_minor hal_api_version/** Identifier of module */const char *id; /** Name of THis module */const char *name; /** Author/owner/implementor of the module */const char *author; /** Modules Methods */<strong> struct hw_module_methods_t* methods;</strong>/** module ' s DSO */<s trong> void* dso;</strong>/** padding to + bytes, reserved for future 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 with hw_device_t * followed by module specific public met Hods and attributes. */typedef struct hw_device_t {/** tag must is initialized to Hardware_device_tag */uint32_t tag; /** * Version of the module-specific device API. This value was used by * The Derived-module user to manage different device implementations. * * The module user is responsible for checking thE module_api_version * and device version fields to ensure, the user is capable of * communicating with the SP Ecific module implementation. * * One module can support multiple devices with different versions. This * can being useful when a device interface changes on an incompatible the-it is still necessary-support Older implementations at the same * time. One such example is the Camera 2.0 API. * * This field was interpreted by the module user and was ignored by the * HAL interface itself. */uint32_t version; /** reference to the module this device belongs to */<strong>struct hw_module_t* module;</strong>/** p Adding reserved for future use */uint32_t reserved[12]; /** Close This device */<strong>int (*close) (struct hw_device_t* device); </strong>} hw_device_t;
4. Use of the Hardware module library
The loading and parsing of the hardware module library is done by the Hw_get_module function in hardware.c, which first chooses the Hardware module library according to certain rules, then resolves the global variable name in the library by Hal_module_info_sym and obtains the Hardware module library pointer (hw_ module_t structure) and then returned to the caller.
The following is a camera example to illustrate how to use the HAL layer.
When the system starts creating a Cameraservice object, its function onfirstref is called, inside it, through Hw_get_module (camera_hardware_module_id, (const hw_module_t**) &mmodule) function Gets the abstract hardware module of the camera Camera_module, its process as described above, through the camera's HAL Dynamic library and then parse the HAL_MODULE_INFO_SYM symbol to get global variables, Then obtain the structure of the camera by acquiring the abstract hardware module. See CameraService.cpp for specific code.
where Camera_module is the abstract hardware module of the camera HAL, which is defined as follows (Camera_common.h):
typedef struct CAMERA_MODULE {hw_module_t common; /** * Get_number_of_cameras: * * Returns the number of camera devices accessible through the camera * modu Le. The camera devices is numbered 0 through N-1, where N was the * value returned by this call. The name of the camera device for open () was * simply the number converted to a string. That's, "0" for camera ID 0, * "1" for camera ID 1. * The value here must is static, and cannot change after the first call to * this method */int (*get_num Ber_of_cameras) (void); /** * Get_camera_info: * * Return the static camera information for a given camera device. This * information is not the change for a camera device. * */INT (*get_camera_info) (int camera_id, struct camera_info *info); /** * Set_callbacks: * * Provide callback function pointers to the HAL module to inform framework * of ASY Nchronous Camera Module events. The framework wouldCall this * function once after initial camera HAL module load, after the * Get_number_of_cameras () method was call Ed for the first time, and before * all other calls to the module. * * Version information (based on camera_module_t.common.module_api_version): * * camera_module_api_version_1 _0, CAMERA_MODULE_API_VERSION_2_0: * * not provided by HAL MODULE. The Framework may not call the This function. * * Camera_module_api_version_2_1: * * Valid to be called by the framework. * */INT (*set_callbacks) (const camera_module_callbacks_t *callbacks); /** * Get_vendor_tag_ops: * * Get methods to query for vendor extension METADATA tag information. The * HAL should fill in all the vendor tag operation methods, or leave OPS * unchanged if no vendor tags is defi Ned. * * Version information (based on camera_module_t.common.module_api_version): * * camera_module_api_version_1 _x/2_0/2_1: *Not provided by HAL module. The Framework may not call the This function. * * Camera_module_api_version_2_2: * Valid to being called by the framework. */void (*get_vendor_tag_ops) (vendor_tag_ops_t* OPS); /* Reserved for future use */void* reserved[8];} camera_module_t;
camera_module_t hal_module_info_sym __attribute__ ((Visibility ("default")) = { Common: {tag:hardware_module_tag, Module_api_version:camera_module_api_version_2_0, Hal_api_version:hardware_hal_api_version, id:camera_hardware_module_id, name : "Default Camera HAL", Author: "The Android Open Source Project", Methods : &gcameramodulemethods, Dso:null, reserved: {0},}, Get_number_of_ca Meras:get_number_of_cameras, Get_camera_info:get_camera_info, Set_callbacks:set_callbacks};
int Camera::open (const hw_module_t *module, hw_device_t **device) { alogi ("%s:%d:opening Camera Device", __func__, MID); Camtrace_call (); Pthread_mutex_lock (&mmutex); if (mbusy) { pthread_mutex_unlock (&mmutex); Aloge ("%s:%d:error! Camera device already opened ", __func__, mId); return-ebusy; } Todo:open camera dev nodes, etc Mbusy = true; MDevice.common.module = const_cast
Here, the camera_device_t is returned, and the initialization of this structure is in the constructor:
</pre><pre>camera::camera (int id) : mId (ID), mstaticinfo (NULL), Mbusy (false), Mcallbackops (null), mstreams (null), mnumstreams (0), msettings (null) { Pthread_mutex_init (& Mmutex, NULL); Pthread_mutex_init (&mstaticinfomutex, NULL); memset (&mdevice, 0, sizeof (mdevice)); MDevice.common.tag = Hardware_device_tag; MDevice.common.version = Camera_device_api_version_3_0; MDevice.common.close = Close_device; Mdevice.ops = const_cast<camera3_device_ops_t*> (&sops); Mdevice.priv = this;}
At this point, Cameraservice gets the hardware abstraction module camera_module_t and abstract device camera_device_t of the camera's HAL layer. With these two structures, you can use the camera function on the upper level. The above code is based on Android4.4/hardware/libhardware/modules/camera, the use of C + + implementation, different hardware manufacturers may be different implementations, but the same is necessary to implement both structures.
5. Summary
- Hal uses Hw_get_module to get the hw_module_t structure.
- The HAL obtains the hw_device_t pointer through Hw_module_t->methods->open and initializes the structure in the hw_device_t in open, including the function pointer (close operation), and so on.
- Two important structures:
hw_module_t: A hardware abstraction module that can be obtained with hw_get_module. It also contains a hw_module_methods_t structure that defines the open method of opening the device.
hw_device_t: Hardware abstraction device, mainly defines some hardware related functions, parameters and so on. This structure is obtained through the open function defined inside the hw_module_methods_t.
The above is basically the content of the Android Hal module, the next one will be an important HAL module of Android Gralloc to see its specific implementation.
Android Hal Module Implementation (RPM)