Preface:
Android has added many drivers based on Linux kernel. The alarm driver is the simplest one. The entire file contains more than 500 lines. As the beginning of a series of articles driving code analysis, I tried to carefully analyze almost all of the function code of this driver, hoping to use this as a good start for reviewing the android driver source code.
Android adds an alarm driver, which is implemented in the kernel_root/driver/RTC/alarm. c file. Android wants to provide an incremental clock (monotonic), which should be based on hardware so that android applications can still run or wake up the device when the device enters the sleep state, to save power.
1. Overview
1.1 Implementation Mechanism
Android alarm runs in hard interrupt based on the hardware clock. However, he does not implement the hardware RTC driver. It is implemented based on the Linux high-precision clock hrtimer.
The Linux high-precision clock is implemented in the kernel_root/kernel/hrtimer. c file.
For the analysis of this Part (high precision clock hrtimer), see the following two blog posts:
Http://blog.csdn.net/walkingman321/article/details/6133171
Http://blog.csdn.net/walkingman321/article/details/6151172
1.2 Implementation Method
Alarm. C registers a platform device in Linux kernel (an RTC device is finally registered and saved in the variable static struct rtc_device * alarm_rtc_dev;). The device node is/dev/alarm.
The user space program opens the node through fopen and obtains the control handle, and then sends a request to the driver through ioctrl.
The following file directly uses this driver:
Android_root/system/CORE/toolbox/alarm. c
Android_root/frameworks/base/serices/JNI/com_android_server_alarmmanagerservice.cpp
Android_root/system/CORE/toolbox/date. c
Android_root/frameworks/base/cmds/runtime/main_runtime.cpp
Android_root/frameworks/base/libs/utils/systemclock. cpp
Android_root/system/CORE/toolbox/uptime. c
1.3 DEMO code using the alarm driver
If you need to directly operate this driver, you can refer to the usage method in the above file.
The following example is taken from systemclock. cpp:
# If have_android_ OS
FD = open ("/dev/alarm", o_rdwr );
If (FD <0 ){
Logw ("unable to open alarm DRIVER: % s \ n", strerror (errno ));
Return-1;
}
TS. TV _sec = TV. TV _sec;
TS. TV _nsec = TV. TV _usec * 1000;
Res = IOCTL (FD, android_alarm_set_rtc, & TS );
If (RES <0 ){
Logw ("unable to set RTC to % ld: % s \ n", TV. TV _sec, strerror (errno ));
Ret =-1;
}
Close (FD );
# Else
If (settimeofday (& TV, null )! = 0 ){
Logw ("unable to set clock to % d. % d: % s \ n ",
(INT) TV. TV _sec, (INT) TV. TV _usec, strerror (errno ));
Ret =-1;
}
# Endif
2. driver code analysis
2.1 list of main functions
Alarm_start_hrtimer tool function. Other alarm-driven functions use this function to create an hrtimer timer for alarm of the corresponding type (android_alarm_type.
The ioctl function of the alarm_ioctl alarm driver. The upper-Layer Code sends an operation request to the driver through this interface.
Alarm_open
Alarm_release
Alarm_timer_triggered
Alarm_triggered_func
Alarm_suspend
Alarm_resume
Rtc_alarm_add_device
Rtc_alarm_remove_device
The post-initialization function of the alarm_late_init Driver runs after alarm_init (see the remarks in this section ).
Alarm_init driver initialization Function
Exit function driven by alarm_exit
Note:For more information about the Linux driver startup sequence (alarm_init and alarm_late_init), see the following blog:
Http://blog.csdn.net/cstk502/article/details/6579231
2.2 alarm_start_hrtimer Function
The code and comments are as follows:
Static void alarm_start_hrtimer (Enum android_alarm_type alarm_type)
{
Struct timespec hr_alarm_time;
If (! (Alarm_enabled & (1u <alarm_type) // determine the enabled type based on the alarm_enabled mask.
Return;
Hr_alarm_time = alarm_time [alarm_type]; // save timespec of this type to a local variable
If (alarm_type = android_alarm_elapsed_realtime_wakeup |
Alarm_type = android_alarm_elapsed_realtime)
Set_normalized_timespec (& hr_alarm_time, // set the time format
Hr_alarm_time. TV _sec + elapsed_rtc_delta. TV _sec,
Hr_alarm_time. TV _nsec + elapsed_rtc_delta. TV _nsec );
// Record the log. The current version has disable this macro, so no logs will appear.
Android_alarm_dprintf (android_alarm_print_flow,
"Alarm start hrtimer % d at % lD. % 09ld \ n ",
Alarm_type, hr_alarm_time. TV _sec, hr_alarm_time. TV _nsec );
// Add an hrtimer for alarm_timer [alarm_type]. If alarm_timer [alarm_type] already has an hrtimer, delete it and then add a new one. See the implementation of the hrtimer_start_range_ns function in hrtimer. C.
Hrtimer_start (& alarm_timer [alarm_type],
Timespec_to_ktime (hr_alarm_time), hrtimer_mode_abs );
}
Conclusion: This function eventually creates an hrtimer for the alarm_type type in the array alarm_timer [alarm_type.
2.3 alarm_init Function
To be continued.