1. Analysis of kernel and Hal Interfaces
The kernel and Hal interfaces are implemented through a system file under/sys/power, such as/sys/power/state.
The file implementation process in/sys/power in kernel is as follows:
1. sysfs attribute File
In kernel/power/Main. C, a set of sysfs attribute files are defined:
static struct attribute * g[] = {&state_attr.attr,#ifdef CONFIG_PM_TRACE&pm_trace_attr.attr,&pm_trace_dev_match_attr.attr,#endif#ifdef CONFIG_PM_SLEEP&pm_async_attr.attr,&wakeup_count_attr.attr,#ifdef CONFIG_PM_DEBUG&pm_test_attr.attr,#endif#ifdef CONFIG_USER_WAKELOCK&wake_lock_attr.attr,&wake_unlock_attr.attr,#endif#endifNULL,};static struct attribute_group attr_group = {.attrs = g,};
For example, state_attr is defined as follows:
Power_attr (State); # define power_attr (_ name) \ static struct kobj_attribute _ name ##_ ATTR = {\. ATTR = {\. name = _ stringify (_ name ),\. mode = 0644 ,\},\. show = _ name ##_ show ,\. store = _ name ##_ store, \}: static struct kobj_attribute state_attr = {\. ATTR = {\. name = "State ",\. mode = 0644 ,\},\. show = state_show ,\. store = state_store ,\}
2. Create a sysfs File
static int __init pm_init(void){int error = pm_start_workqueue();if (error)return error;hibernate_image_size_init();hibernate_reserved_size_init();power_kobj = kobject_create_and_add("power", NULL);if (!power_kobj)return -ENOMEM;return sysfs_create_group(power_kobj, &attr_group);}
After the pm_init function is executed, the/sys/power directory is created, and a series of attribute files are created under the directory, one of which is the/sys/power/State file. User spaceWriteThis file will cause state_store to be called,ReadThis file will cause the state_show function to be called.
Ii. Hal code analysis
Hal code is located in hardware/libhardware_legacy/power. c
1. Path and write string Definition
const char * const NEW_PATHS[] = { "/sys/power/wake_lock", "/sys/power/wake_unlock", "/sys/power/state"};static const char *off_state = "mem";static const char *on_state = "on";
2. Open the three files defined above
static intopen_file_descriptors(const char * const paths[]){ int i; for (i=0; i<OUR_FD_COUNT; i++) { int fd = open(paths[i], O_RDWR); if (fd < 0) { fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]); g_error = errno; return -1; } g_fds[i] = fd; } g_error = 0; return 0;}
3. modify the status
The user-mode power management system calls the set_screen_state function to trigger the suspend process. This function is actually writing the "mem" or "on" command string to the/sys/power/State file.
intset_screen_state(int on){ QEMU_FALLBACK(set_screen_state(on)); LOGI("*** set_screen_state %d", on); initialize_fds(); //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime, // systemTime(), strerror(g_error)); if (g_error) goto failure; char buf[32]; int len; if(on) len = snprintf(buf, sizeof(buf), "%s", on_state); else len = snprintf(buf, sizeof(buf), "%s", off_state); buf[sizeof(buf) - 1] = '\0'; len = write(g_fds[REQUEST_STATE], buf, len); if(len < 0) { failure: LOGE("Failed setting last user activity: g_error=%d\n", g_error); } return 0;}