Android layered learning notes (1)

Source: Internet
Author: User

For Android system transplantation, it mainly refers to the migration of framework in information, and hardware is involved. For more information about hardware, jollen is the first to describe jollen. Most of the other information is based on his analysis. His blog address is http://www.jollen.org/blog/2009 /.

 

 

The following are your learning notes and understandings, and you may wish to forget them.

 

The main content of this article is as follows:

Preface: about layering

I. Stub compiling

Ii. Compiling JNI

Iii. Compiling framework in Java

4. Application Programming

V. Writing Linux hardware drivers

 

Try to make every part of the House shorter. If it is too long, it will be quite tiring.

------------------------------------------------------------------------------

Preface: about layering

The hierarchy of a system can have a clear sense of attention. Basically, our world is in a layered concept, namely, the biosphere, management, administrative system, and human needs ...... You can see the shadow of the layer, there are some logical concepts, such as TCP/IP layer.

Sometimes we call it a level.

The layering cannot be too many layers; otherwise, it cannot be reached. It cannot be too small. Otherwise, the layer is too wide and the essentials of layering are lost. The appropriate, effective, and robust hierarchy is what we often call "moderate". Of course, this is moderate, rather than moderate.

The hierarchy of the anroid system is clearly shown in a figure. This figure is shown more on the Internet and skipped here. Apps-> framework (apps service, Manager)-> JNI-> stub-> Linux kernel/driver.

For the entire system, this layer is indeed too multi-layer. If you don't have to spend some time, you will lose your mind and have a wide range of knowledge.

For efficiency, there are too many layers and the efficiency will be compromised. Moreover, applications are still written in Java, a relatively advanced Java language. Currently, the android system has high hardware requirements. It seems that these discounts can be compensated by hardware. Is there a bottleneck in the development of hardware and hardware ??

 

I. Stub compiling

1. Writing stub

Stub is dealing with Linux drivers, that is, directly calling open, close, ioctl, read, write and other functions. In fact, it is equivalent to calling the hardware driver function when writing some applications on Linux. It's just called stub in Android.

First, get familiar with the two struct: hw_module_t and hw_device_t.

The two struct types are defined in hardware/libhardware/include/hardware. h.

Typedef struct hw_module_t {<br/>/** tag must be initialized to hardware_module_tag */<br/> uint32_t tag; <br/>/** major version number for the module */<br/> uint16_t version_major; <br/>/** minor version number of the module */<br/> uint16_t version_minor; <br/>/** identifier of module */<br/> const char * ID; <br/>/** name of this module */<br/> const char * Name; <br/>/** author/owner/implementor of the module */<br/> const char * author; <br/>/** modules Methods */<br/> struct hw_module_methods_t * methods; <br/>/** module's DSO */<br/> void * DSO; <br/>/** padding to 128 bytes, reserved for future use */<br/> uint32_t reserved [32-7]; <br/>} hw_module_t; <br/> typedef struct hw_module_methods_t {<br/>/** open a specific device */<br/> int (* open) (construst hw_module_t * module, const char * ID, <br/> struct hw_device_t ** device); <br/>} hw_module_methods_t; <br/>/** <br/> * every device data structure must begin with hw_device_t <br/> * followed by module specific public methods and attributes. <br/> */<br/> typedef struct hw_device_t {<br/>/** tag must be initialized to hardware_device_tag */<br/> uint32_t tag; <br/>/** version number for hw_device_t */<br/> uint32_t version; <br/>/** reference to the module this device belongs to */<br/> struct hw_module_t * module; <br/>/** padding reserved for future use */<br/> uint32_t reserved [12]; <br/>/** close this device */<br/> int (* close) (struct hw_device_t * Device); <br/>} hw_device_t;

 

Write the stub code to fill these two bodies.

When accessing a hardware device, it is operated by the file ID. Therefore, in fact, the hw_device_t should also add a file ID to change FD. There are two ways to achieve this: 1) put the reseverd variable in hw_device_t to the file ID, which is retained by the system and should be said to be unsafe. 2) define a struct and treat hw_device_t as a member variable of the struct. Follow these steps:

Struct gpio_device_t {
Struct hw_device_t hwdev;

/* Attributes */
Int FD; // The file description of the device in/dev/xxx

}

In this way, you can pass the returned File ID value to fd when you open the device.

 

The following is a simple process for writing stub:

1. Create a Hal directory under the vendor directory, and then create the frameworks and modules directories respectively. Create a gpio directory in moueles for the Framework Code and C/C ++ module code. Gpio is common, and LED is also in the gpio category.

2. Create gpio. h as follows:

# Include <Hardware/hardware. h> <br/> # include <fcntl. h> <br/> # include <errno. h> <br/> # include <cutils/log. h> <br/> # include <cutils/atomic. h> <br/> struct gpio_module_t {<br/> struct hw_module_t hwmod; <br/>}; <br/> struct gpio_device_t {<br/> struct hw_device_t hwdev; <br/>/* attributes */<br/> int FD; // The file description of the device in/dev/xxx <br/>/* supporting control APIs go here */<br/> int (* setgpio) (struct gpio_device_t * Dev, int32_t gpio); <br/> int (* clrgpio) (struct gpio_device_t * Dev, int32_t gpio); <br/> }; <br/> # define gpio_hardware_module_id "gpio"

Header file:

# Include <Hardware/hardware. h> // The first two basic struct Definitions

# Include <fcntl. h>
# Include <errno. h>

# Include <cutils/log. h>
# Include <cutils/Atomic. h>

 

Two struct types defined by yourself

Struct gpio_module_t {
Struct hw_module_t hwmod;
};

Struct gpio_device_t {
Struct hw_device_t hwdev;

Int FD; // The file description of the device in/dev/xxx

INT (* setgpio) (struct gpio_device_t * Dev, int32_t gpio );
INT (* clrgpio) (struct gpio_device_t * Dev, int32_t gpio );
};

Define a module ID, # define gpio_hardware_module_id "gpio"

Save it to the gpio directory.

 

3. Write gpio. c

# Include "gpio. H "<br/> # define log_tag" gpio "<br/> int gpio_device_close (struct hw_device_t * device) <br/>{< br/> struct gpio_device_t * gdev = (struct gpio_device_t *) device; <br/> If (gdev) <br/>{< br/> free (gdev); <br/>}< br/> return 0; <br/>}< br/> int gpio_set (struct gpio_device_t * Dev, int32_t gpio) <br/>{< br/> Logi ("gpio: % d set. ", gpio); <br/> If (Dev-> FD> = 0) <br/>{</P> <p >}< br/> return 0; <br/>}< br/> int gpio_clr (struct gpio_device_t * Dev, int32_t gpio) <br/>{< br/> Logi ("gpio: % d CLR. ", gpio); <br/> If (Dev-> FD> = 0) <br/>{</P> <p >}< br/> return 0; <br/>}< br/> static int gpio_device_open (const struct hw_module_t * module, const char * Name, <br/> struct hw_device_t ** device) <br/>{< br/> struct gpio_device_t * dev; <br/> Dev = (struct gpio_device_t *) malloc (sizeof (struct gpio_device_t )); <br/> memset (Dev, 0, sizeof (struct gpio_device_t); <br/> Dev-> hwdev. tag = hardware_device_tag; <br/> Dev-> hwdev. version = 0; <br/> Dev-> hwdev. module = module; <br/> Dev-> hwdev. close = gpio_device_close; <br/> Dev-> setgpio = gpio_set; <br/> Dev-> clrgpio = gpio_clr; <br/> Dev-> FD = open ("/dev/gpio0", o_rdwr); <br/> * Device = & Dev-> hwdev; <br/> If (Dev-> FD <0) <br/>{< br/> free (Dev); <br/> Dev = NULL; <br/> return-1; <br/>}< br/> return 0; <br/>}< br/> static struct hw_module_methods_t gpio_module_methods = <br/>{< br/> open: gpio_device_open <br/> }; <br/> const struct gpio_module_t hal_module_info_sym = <br/>{< br/> hwmod: <br/>{< br/> tag: hardware_module_tag, <br/> version_major: 1, <br/> version_minor: 0, <br/> ID: gpio_hardware_module_id, <br/> name: "gpio stub", <br/> author: "guim ", <br/> Methods: & gpio_module_methods, <br/>}</P> <p> };

Int gpio_device_close (struct hw_device_t * Device) // disable the gpio Device

 

Int gpio_set (struct gpio_device_t * Dev, int32_t gpio) // set gpio to 1

Int gpio_clr (struct gpio_device_t * Dev, int32_t gpio) // set gpio to 0

 

Static int gpio_device_open (const struct hw_module_t * module, const char * Name,
Struct hw_device_t ** device) // to enable the gpio device, this function must be implemented, because it will be passed to the open function pointer in hw_module_methods_t:

Static struct hw_module_methods_t gpio_module_methods =
{
Open: gpio_device_open
};

In this function, you need to fill in some gpio_device_t interfaces for the upper layer to call:

Dev-> hwdev. Tag = hardware_device_tag; // Default Value
Dev-> hwdev. Version = 0; // you can write it as needed.
Dev-> hwdev. module = module;
Dev-> hwdev. Close = gpio_device_close;

Dev-> setgpio = gpio_set;
Dev-> clrgpio = gpio_clr;
Dev-> FD = open ("/dev/gpio0", o_rdwr); // enable the gpio Device

// Registration interface, hal_module_info_sym

Const struct gpio_module_t hal_module_info_sym = // It is invariably set to hal_module_info_sym and cannot be modified. I do not know why.
{
Hwmod:
{
Tag: hardware_module_tag,
Version_major: 1,
Version_minor: 0,
ID: gpio_hardware_module_id,
Name: "gpio stub ",
Author: "guim ",
Methods: & gpio_module_methods,
}

};

 

4. Compile the Android. mk File

Local_path: = $ (call my-DIR)
Include $ (clear_vars)
Local_prelink_module: = false
Local_module_path: = $ (target_out_shared_libraries)/HW
Local_shared_libraries: = liblog
Local_src_files: = gpio. c

# Module name: gpio. Default
Local_module: = gpio. Default
Include $ (build_shared_library)

 

Set local_prelink_module to false. Otherwise, an error occurs during compilation.

 

5. Module name

When JNI calls the stub method, the hw_get_module function is used to find this library. The hw_get_module function is implemented as follows (location: Hardware/libhardware/hardware. C ):

When searching for a module, the system/lib/hwh directory is searched by default, that is, the compiled gpio. Default. So is stored in this directory.

# Define hal_library_path "/system/lib/HW"

// Module key value. When searching for a library, you need to find the module File Based on the module ID, that is, gpio_hardware_module_id.
Static const char * variant_keys [] = {
"Ro. Hardware",/* This goes first so that it can pick up a different file on the emulator .*/

"Ro. Product. Board ",
"Ro. Board. Platform ",
"Ro. Arch"
};

Static const int hal_variant_keys_count =
(Sizeof (variant_keys)/sizeof (variant_keys [0]);
Int hw_get_module (const char * ID, const struct hw_module_t ** module)
{
Int status;
Int I;
Const struct hw_module_t * HMI = NULL;
Char prop [path_max];
Char path [path_max];

/*
* Here we rely on the fact that calling dlopen multiple times on
* The same. So will simply increment a refcount (and not load
* A new copy of the library ).
* We also assume that dlopen () is thread-safe.
*/

/* Loop through the configuration variants looking for a module */
For (I = 0; I If (I If (property_get (variant_keys, prop, null) = 0 ){
Continue;
}
Snprintf (path, sizeof (PATH), "% S/% S. % S. So ",
Hal_library_path, ID, Prop );
} Else {
Snprintf (path, sizeof (PATH), "% S/% S. Default. So ",
Hal_library_path, ID );
}
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 );
}

Return status;
}

 

Property_get (variant_keys, prop, null) obtains the value of the corresponding variable from the variant_keys array and returns it to prop:
The values of the variables in the array are as follows:
"Ro. Product. Board = $ target_bootloader_board_name"
"Ro. Board. Platform = $ target_board_platform"

Target_bootloader_board_name will be determined based on the specific settings. Of course, you must check the target selected when compiling the Android system. The default options are genic, and target_bootloader_board_name and target_board_platform are empty. Therefore, the corresponding module file cannot be found here. If it is found, it will be passed to the prop value, and then according to snprintf (path, sizeof (PATH), "% S/% S. % S. so ", hal_library_path, ID, Prop); obtain the absolute File Name of the module. Otherwise, snprintf (path,
Sizeof (PATH), "% S/% S. default. so ", hal_library_path, ID); set the full path name of the module, that is,/system/lib/HW/xxx. default. so. Therefore, the above generation module name is defined as gpio. Default. So. Here XXX is gpio. If no module File is found, an error is prompted during upper-layer calling. You can use log information to track the error.

This part of details will be discussed in detail by JNI.

 

 

 

Related Article

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.