Transferred from[It168 Technology]
As developers, we all know that the vibrator is responsible for controlling the vibration function of the mobile phone. The Vibrator System in Android is a small system dedicated to this function and provides the time-based Vibration function.
The vibrator system includes the driver, hardware abstraction layer, JNI, and Java framework. It also provides a simple API to the Java application layer as a platform interface.
The basic hierarchy of Android vibrator is shown in Figure 23-1.
▲Figure 23-1 Basic hierarchy of the android Vibrator System
1. structure diagram of Android Vibrator
The android vibrator system consists of the driver, the hardware abstraction layer of the vibrator system, the Java framework of the vibrator system, and the use of the vibrator system in the Java framework. Its structure is 23-2.
▲Figure 23-2 Structure of the android Vibrator System
From the bottom up, the android vibrator system is divided into the following parts.
(1) DRIVER:The driver of the vibrator on a specific hardware platform is usually implemented based on the timed output driver framework of Android.
(2) Hardware Abstraction Layer
The interface path of the hardware abstraction layer of the optical system is hardware/libhardware_legacy/include/hardware_legacy/vibrator. h.
The Hardware Abstraction Layer of the vibrator system has the default implementation in Android. The code path is as follows:
Hardware/libhardware_legacy/vibrator. c
The Hardware Abstraction Layer of the vibrator usually does not need to be implemented again. It is part of libhardware_legacy.so.
(3) JNI Section
Code path: Frameworks/base/services/JNI/com_android_server_vibratorservice.cpp
This class is the JNI part of the vibrator and provides interfaces to the upstream layer by calling the hardware abstraction layer.
(4) Java Section
Code path:
Frameworks/base/services/Java/COM/Android/Server/vibratorservice. Java
Frameworks/base/CORE/Java/Android/OS/vibrator. Java
Vibratorservice. Java implements the vibratorservice class in the com. Android. server package by calling vibratorservice JNI. This class is not a platform API and is called by a small part of the Java framework of the Android system.
The Vibrator. Java file implements the vibrator class in the Android. OS package, which is an API provided to the Java layer.
Ii. Main Contents of transplantation
There are two ways to port the vibrator system to a specific hardware platform.
Method 1 (usually): Because the hardware abstraction layer is already in place, only the driver program needs to be implemented to transplant the vibrator system. This driver must be based on the timed output driver framework in the android kernel.
Method 2: Re-implement the hardware abstraction layer interface of the vibrator according to the self-implemented Driver (which must be in the libhardware_legacy.so library). Because the interface of the hardware abstraction layer of the vibrator is very simple, therefore, this implementation method is not very complex.
Precautions for vibrator transplantation and debugging
1. Drivers
Vibrator drivers only need to implement the vibration interface, which is an output device and must accept the vibration time as a parameter. Because it is relatively simple, vibrator drivers can be implemented in multiple ways.
In Android, we recommend that you define the timed output driver framework based on the android kernel to implement the vibrator driver.
Timed output refers to scheduled output, which is used to periodically send an output. In fact, the driver is still based on the Sys File System.
Drivers/staging/Android/directory timed_output.h defines the timed_output_dev struct, which contains the Enable and get_time function pointers. after implementing the struct, use timed_output_dev_register () and register () function registration and logout.
The timed output driver framework creates a subdirectory for each device in the/sys/class/timed_output/directory. The enable file in the subdirectory is the control file of the device. Reading the enable file indicates obtaining the remaining time. Writing this file indicates time-based vibration.
Debug the timed output driver through the Sys File System.
For the vibrator device, the implementation of the timed output driver should be named "vibrator ". Therefore, the method of vibrator in SYS file system is as follows:
# Echo "10000">/sys/class/timed_output/vibrator/enable <br/> # Cat/sys/class/timed_output/vibrator/enable <br/> 3290 <br/> # echo "0">/sys/class/timed_output/vibrator/enable <br/>
For an enable file, "write" indicates the time specified for enabling, and "read" indicates obtaining the remaining time.
Ii. Hardware Abstraction Layer content
1. Hardware Abstraction Layer Interface
The Vibrator hardware abstraction layer interface is defined in the vibrator. h file of the hardware/libhardware_legacy/include/hardware_legacy/directory:
Int vibrator_on (INT timeout_ms); // start vibration <br/> int vibrator_off (); // close vibration <br/>
The Vibrator. h file defines two interfaces, indicating vibration and shutdown, respectively, starting with Millisecond (MS) as the unit of time.
Tip: The timed output driver has the ability to obtain the remaining time (read the enable file). However, this function is not used on all interfaces above the hardware abstraction layer of Android vibrator.
II. Implementation of the standard hardware abstraction layer
The Vibrator hardware abstraction layer has standard implementation in vibrator. c In the hardware/libhardware_legacy/vibrator/directory.
The core content of the implementation is the sendit () function. The content of this function is as follows:
# Define the_device "/sys/class/timed_output/vibrator/enable" <br/> static int sendit (INT timeout_ms) <br/>{< br/> int nwr, RET, FD; <br/> char value [20]; <br/> # ifdef qemu_hardware // qemu usage <br/> If (qemu_check ()) {<br/> return qemu_control_command ("vibrator: % d", timeout_ms); <br/>}< br/># endif <br/> FD = open (the_device, o_rdwr); // read the contents in the Sys File System <br/> If (FD <0) return errno; <br/> nwr = Sp Rintf (value, "% d/N", timeout_ms); <br/> ret = write (FD, value, nwr); <br/> close (FD ); <br/> return (ret = nwr )? 0:-1; <br/>}< br/>
The sendit () function is responsible for "vibration" based on time: in real hardware, it controls the file through the Sys File System; in a simulator environment, it sends commands through qemu.
Vibrator_on () calls sendit () with time as the parameter, and vibrator_on () calls sendit () with 0 as the parameter.
Iii. Upper-layer situations and precautions
The com_android_server_vibratorservice.cpp file in the frameworks/base/services/JNI/directory is the caller of the vibrator hardware abstraction layer. It also provides JNI support to Java.
The list of methods defined for JNI is as follows:
Static jninativemethod method_table [] = {<br/> {"vibratoron", "(j) V", (void *) vibratoron }, // vibrator <br/> {"vibratoroff", "() V", (void *) vibratoroff} // vibrator off <br/> }; <br/> int encode (jnienv * env) {<br/> return jniregisternativemethods (ENV, "com/Android/Server/vibratorservice", <br/> method_table, nelem (method_table); <br/>}< br/>
The functions vibratoron () and vibratoroff () are implemented as follows:
Static void vibratoron (jnienv * ENV, jobject clazz, jlong timeout_ms) {<br/> vibrator_on (timeout_ms ); <br/>}< br/> static void vibratoroff (jnienv * ENV, jobject clazz) {<br/> vibrator_off (); <br/>}< br/>
Vibratorservice. Java in frameworks/base/services/Java/COM/Android/Server/directory implements the vibratorservice class in the com. Android. server package by calling vibratorservice JNI.
The Vibrator. Java file in the frameworks/base/CORE/Java/Android/OS/directory implements the vibrator class in the Android. OS package. It is implemented by calling the Java service of vibrator (to obtain the service named vibrator), and works with the ivibratorservice. aidl file in the same directory to provide relevant APIs of vibrator to the application layer.
Implementation in MSM
In the mahimahi platform of MSM, vibrator is implemented based on the timed output driver framework. Therefore, the hardware abstraction layer is not required.
The driver of vibrator is implemented in the msm_vibrator.c file in the arch/ARM/Mach-MSM/directory of the kernel.
The core implementation of msm_vibrator.c is the set_pmic_vibrator () function. The implementation content is as follows:
Static void set_pmic_vibrator (INT on) <br/>{< br/> static struct msm_rpc_endpoint vib_endpoint; /* define the RPC endpoint */<br/> struct set_vib_on_off_req {<br/> struct rpc_request_hdr; <br/> uint32_t data; <br/>} req; <br/> If (! Vib_endpoint) {<br/> vib_endpoint = msm_rpc_connect (pm_libprog, pm_libvers, 0); <br/> /*...... partial content omitted */<br/>}< br/> If (on) <br/> req. data = cpu_to_be32 (pmic_vibrator_level);/* GET request time */<br/> else <br/> req. data = cpu_to_be32 (0); <br/> msm_rpc_call (vib_endpoint, htc_procedure_set_vib_on_off, & req, <br/> sizeof (req), 5 * Hz ); /* Call RPC */<br/>}< br/>
The set_pmic_vibrator () function implements specific functions through the Remote Procedure Call (RPC) of the MSM system. The call command is specified by htc_procedure_set_vib_on_off.
The initialization process of this driver is as follows:
Void _ init msm_init_pmic_vibrator (void) <br/>{< br/> init_work (& vibrator_work, update_vibrator ); /* Create A Message Queue */<br/> maid (& vibe_lock); <br/> vibe_state = 0; <br/> hrtimer_init (& vibe_timer, clock_monotonic, hrtimer_mode_rel ); /* timer */<br/> vibe_timer.function = timer; <br/> timed_output_dev_register (& pmic_vibrator);/* Register timed_output_dev device */<br/>} <br/>
Vibrator_work is work_struct type. In the queue execution function update_vibrator, call the set_pmic_vibrator () function.
Pmic_vibrator is a timed_output_dev device. The enable function pointer implements vibrator_enable to start the timer based on the input value and perform output operations to the scheduling queue. The implementation of the get_time function pointer vibrator_get_time only obtains the remaining time from the timer.
The reason for using the timer to add a queue is that the Enable call will form a duration effect, but the call itself should not be blocked. Therefore, after the vibrator_enable function exits, the timer is used to achieve the effect.