Android睡眠唤醒机制--系统架构
2012-11-01 17:57
337 查看
一、简介
Android在Linux内核原有的睡眠唤醒模块上基础上,主要增加了下面三个机制:
• Wake Lock 唤醒锁机制;
• Early Suspend 预挂起机制;
• Late Resume 迟唤醒机制;
其基本原理:当启动一个应用程序的时候,它可以申请一个wake_lock唤醒锁,每当申请成功之后都会在内核中注册一下(通知系统内核,现在已经有锁被申请,系统内核的wake_lock_store把它加入红黑树中),当应用程序在某种情况下释放wake_lock的时候,会注销之前所申请的wake_lock。特别要注意的是:只要是系统中有一个wake_lock的时候,系统此时都不能进行睡眠。但此时各个模块可以进行early_suspend。当系统中所有的wake_lock都被释放之后,系统就会进入真正的kernel的睡眠状态。在系统启动的时候会创建一个主唤醒锁main_wake_lock,该锁是内核初始化并持有的一个WAKE_LOCK_SUSPEND属性的非限时唤醒锁。因此,系统正常工作时,将始终因为该锁被内核持有而无法进入睡眠状态。也就是说在不添加新锁的情况下,只需将main_wake_lock
解锁,系统即可进入睡眠状态。
从Android最上层(Java的应用程序),经过Java、C++和C语言写的Framework层、JNI层、HAL层最后到达android的最底层(Kernel层)。
下图是Android睡眠唤醒模块框架:
二、相关代码
• Frameworks
// 供给上层应用程序调用的接口
frameworks/base/core/java/android/os/PowerManager.java
// 具体实现PowerManager类中的接口
frameworks/base/services/java/com/android/server/PowerManagerService.java
// 被PowerManagerService类调用
frameworks/base/core/java/android/os/ Power.java
• JNI
// 实现Power类中的JNI接口
frameworks/base/core/jni/android_os_Power.cpp
• HAL
// 进行sysfs用户接口的操作
hardware/libhardware_legacy/power/power.c
• Kernel
kernel/kernel/power/main.c
kernel/kernel/power/earlysuspend.c
kernel/kernel/power/suspend.c
kernel/kernel/power/wakelock.c
kernel/kernel/power/userwakelock.c
在应用程序框架层中,PowerManager类是面向上层应用程序的接口类,提供了Wake Lock机制(同时也是睡眠唤醒子系统)的基本接口(唤醒锁的获取和释放)。上层应用程序通过调用这些接口,实现对系统电源状态的监控。
• PowerManager类通过IBinder这种Android中特有的通信模式,与PowerManagerService 类进行通信。
• PowerManagerService 是PowerManager 类中定义的接口的具体实现,并进一步调用Power 类来与下一层进行通信。PowerManagerService 类是WakeLock 机制在应用程序框架层的核心,他们对应用程调用PowerManager类接口时所传递的参数进行初步的分析和对应的设置,并管理一个唤醒锁队列,然后配合其他模块(例如WatchDog、BatteryService、ShutdownThread
等)的状态信息,做出决策,调用Power类的对应接口,最终通过JNI 接口,调用到硬件抽象层中的函数,对sysfs 的用户接口进行操作,从而触发内核态实现的功能。
三、获得wakelock唤醒锁
比如在应用程序中,当获得wakelock唤醒锁的时候,它首先调用/android/frameworks/base/core/java/android/os/PowerManager类中的public void acquire()办法,而此方法通过Binder将调用PowerManagerService类中的public void acquireWakeLock。
在用户态的调用流程如下:
上述write实质上是文件sysfs: /sys/power/wake_lock,当write时,它将调用userwakelock.c::wake_lock_store()函数,其实现如下:
1. 根据name在红黑树中查找user_wake_lock,若找到则直接返回;否则为它分配内存、调用wake_lock_init初始化、然后增加到红黑树中。
2. 调用wake_lock或wake_lock_timeout,它将调用wake_lock_internal
wake_lock_internal()函数流程:
1) 判断锁的类型是否有效,即是否为WAKE_LOCK_SUSPEND或WAKE_LOCK_IDLE某一种
2) 如果定义了CONFIG_WAKELOCK_STAT, 则更新struct wake_lock里面的用于统计锁信息的成员变量
3) 将锁从inactive_locks链表上取下,加到active_wake_locks链表上。如果是超期锁则设置锁的flag|=WAKE_LOCK_AUTO_EXPIRE,否则取消WAKE_LOCK_AUTO_EXPIRE标志。如果锁是WAKE_LOCK_SUSPEND型的,则继续下面的步骤。
4) 对于WAKE_LOCK_SUSPEND型的锁如果它是超期锁,则调用has_wake_lock_locked函数检查所有处于活动状态的WAKE_LOCK_SUSPEND锁(即在active_wake_locks链表上的WAKE_LOCK_SUSPEND锁,或者说当前被加锁了的WAKE_LOCK_SUSPEND锁),是否有超期锁已经过期,如果有则把过期超期锁从active_wake_locks上删除,挂到inactive_locks上。同时它还检查链表上有没有非超期锁,如果有则直接返回-1,否则它最终返回的是所有超期锁过期时间的最大值
5) 如果has_wake_lock_locked函数返回的是-1(表示当前活动锁有非超时锁)或者0(表示所有活动锁都是超时锁,且全已经超时),则删除expire_timer,并排队一个suspend工作到suspend_work_queue工作队列,最终系统会suspend。suspend函数完成suspend系统的任务,它是suspend_work这个工作的处理函数,suspend_workk排队到suspend_work_queue工作队列中,最终系统会处理这个work,调用其handler即suspend函数。该函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend()就会调用
enter_state()来进入 linux的suspend流程。
四、系统进入睡眠(suspend)
当按了MID上的power键,经过一系统列的事务处理后,它会调用到PowerManager类中的goToSleep。在用户态的调用流程如下所示:
上面的write将把"mem"写入/sys/power/state中。接下来,在kernel态,state_store函数将被调用。
• Android特有的earlysuspend: request_suspend_state(state)
• Linux标准的suspend: enter_state(state)
在state_store中,若定义了CONFIG_EARLYSUSPEND,则执行request_suspend_state(state)以先进入earlysuspend,然后根据wake_lock的状态决定是否进入suspend;否则直接执行enter_state(state)以进入suspend状态。
Android在Linux内核原有的睡眠唤醒模块上基础上,主要增加了下面三个机制:
• Wake Lock 唤醒锁机制;
• Early Suspend 预挂起机制;
• Late Resume 迟唤醒机制;
其基本原理:当启动一个应用程序的时候,它可以申请一个wake_lock唤醒锁,每当申请成功之后都会在内核中注册一下(通知系统内核,现在已经有锁被申请,系统内核的wake_lock_store把它加入红黑树中),当应用程序在某种情况下释放wake_lock的时候,会注销之前所申请的wake_lock。特别要注意的是:只要是系统中有一个wake_lock的时候,系统此时都不能进行睡眠。但此时各个模块可以进行early_suspend。当系统中所有的wake_lock都被释放之后,系统就会进入真正的kernel的睡眠状态。在系统启动的时候会创建一个主唤醒锁main_wake_lock,该锁是内核初始化并持有的一个WAKE_LOCK_SUSPEND属性的非限时唤醒锁。因此,系统正常工作时,将始终因为该锁被内核持有而无法进入睡眠状态。也就是说在不添加新锁的情况下,只需将main_wake_lock
解锁,系统即可进入睡眠状态。
从Android最上层(Java的应用程序),经过Java、C++和C语言写的Framework层、JNI层、HAL层最后到达android的最底层(Kernel层)。
下图是Android睡眠唤醒模块框架:
二、相关代码
• Frameworks
// 供给上层应用程序调用的接口
frameworks/base/core/java/android/os/PowerManager.java
// 具体实现PowerManager类中的接口
frameworks/base/services/java/com/android/server/PowerManagerService.java
// 被PowerManagerService类调用
frameworks/base/core/java/android/os/ Power.java
• JNI
// 实现Power类中的JNI接口
frameworks/base/core/jni/android_os_Power.cpp
• HAL
// 进行sysfs用户接口的操作
hardware/libhardware_legacy/power/power.c
• Kernel
kernel/kernel/power/main.c
kernel/kernel/power/earlysuspend.c
kernel/kernel/power/suspend.c
kernel/kernel/power/wakelock.c
kernel/kernel/power/userwakelock.c
在应用程序框架层中,PowerManager类是面向上层应用程序的接口类,提供了Wake Lock机制(同时也是睡眠唤醒子系统)的基本接口(唤醒锁的获取和释放)。上层应用程序通过调用这些接口,实现对系统电源状态的监控。
• PowerManager类通过IBinder这种Android中特有的通信模式,与PowerManagerService 类进行通信。
• PowerManagerService 是PowerManager 类中定义的接口的具体实现,并进一步调用Power 类来与下一层进行通信。PowerManagerService 类是WakeLock 机制在应用程序框架层的核心,他们对应用程调用PowerManager类接口时所传递的参数进行初步的分析和对应的设置,并管理一个唤醒锁队列,然后配合其他模块(例如WatchDog、BatteryService、ShutdownThread
等)的状态信息,做出决策,调用Power类的对应接口,最终通过JNI 接口,调用到硬件抽象层中的函数,对sysfs 的用户接口进行操作,从而触发内核态实现的功能。
三、获得wakelock唤醒锁
比如在应用程序中,当获得wakelock唤醒锁的时候,它首先调用/android/frameworks/base/core/java/android/os/PowerManager类中的public void acquire()办法,而此方法通过Binder将调用PowerManagerService类中的public void acquireWakeLock。
在用户态的调用流程如下:
PowerManager.acquire()-> PowerManager.acquireLocked()-> PowerManagerService.acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws)-> PowerManagerService.acquireWakeLockLocked(int flags, IBinder lock, int uid, int pid, String tag, WorkSource ws)-> Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME)-> android_os_Power.cpp::acquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj)-> power.c::acquire_wake_lock(int lock, const char* id)-> write(fd, id, strlen(id))
上述write实质上是文件sysfs: /sys/power/wake_lock,当write时,它将调用userwakelock.c::wake_lock_store()函数,其实现如下:
ssize_t wake_lock_store( struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { long timeout; struct user_wake_lock *l; mutex_lock(&tree_lock); l = lookup_wake_lock_name(buf, 1, &timeout); if (IS_ERR(l)) { n = PTR_ERR(l); goto bad_name; } if (debug_mask & DEBUG_ACCESS) pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout); if (timeout) wake_lock_timeout(&l->wake_lock, timeout); else wake_lock(&l->wake_lock); bad_name: mutex_unlock(&tree_lock); return n; }
1. 根据name在红黑树中查找user_wake_lock,若找到则直接返回;否则为它分配内存、调用wake_lock_init初始化、然后增加到红黑树中。
2. 调用wake_lock或wake_lock_timeout,它将调用wake_lock_internal
static void wake_lock_internal( struct wake_lock *lock, long timeout, int has_timeout) { int type; unsigned long irqflags; long expire_in; spin_lock_irqsave(&list_lock, irqflags); type = lock->flags & WAKE_LOCK_TYPE_MASK; BUG_ON(type >= WAKE_LOCK_TYPE_COUNT); BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED)); #ifdef CONFIG_WAKELOCK_STAT if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) { if (debug_mask & DEBUG_WAKEUP) pr_info("wakeup wake lock: %s\n", lock->name); wait_for_wakeup = 0; lock->stat.wakeup_count++; } if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) && (long)(lock->expires - jiffies) <= 0) { wake_unlock_stat_locked(lock, 0); lock->stat.last_time = ktime_get(); } #endif if (!(lock->flags & WAKE_LOCK_ACTIVE)) { lock->flags |= WAKE_LOCK_ACTIVE; #ifdef CONFIG_WAKELOCK_STAT lock->stat.last_time = ktime_get(); #endif } list_del(&lock->link); if (has_timeout) { if (debug_mask & DEBUG_WAKE_LOCK) pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n", lock->name, type, timeout / HZ, (timeout % HZ) * MSEC_PER_SEC / HZ); lock->expires = jiffies + timeout; lock->flags |= WAKE_LOCK_AUTO_EXPIRE; list_add_tail(&lock->link, &active_wake_locks[type]); } else { if (debug_mask & DEBUG_WAKE_LOCK) pr_info("wake_lock: %s, type %d\n", lock->name, type); lock->expires = LONG_MAX; lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE; list_add(&lock->link, &active_wake_locks[type]); } if (type == WAKE_LOCK_SUSPEND) { current_event_num++; #ifdef CONFIG_WAKELOCK_STAT if (lock == &main_wake_lock) update_sleep_wait_stats_locked(1); else if (!wake_lock_active(&main_wake_lock)) update_sleep_wait_stats_locked(0); #endif if (has_timeout) expire_in = has_wake_lock_locked(type); else expire_in = -1; if (expire_in > 0) { if (debug_mask & DEBUG_EXPIRE) pr_info("wake_lock: %s, start expire timer, " "%ld\n", lock->name, expire_in); mod_timer(&expire_timer, jiffies + expire_in); } else { if (del_timer(&expire_timer)) if (debug_mask & DEBUG_EXPIRE) pr_info("wake_lock: %s, stop expire timer\n", lock->name); if (expire_in == 0) queue_work(suspend_work_queue, &suspend_work); } } spin_unlock_irqrestore(&list_lock, irqflags); }
wake_lock_internal()函数流程:
1) 判断锁的类型是否有效,即是否为WAKE_LOCK_SUSPEND或WAKE_LOCK_IDLE某一种
2) 如果定义了CONFIG_WAKELOCK_STAT, 则更新struct wake_lock里面的用于统计锁信息的成员变量
3) 将锁从inactive_locks链表上取下,加到active_wake_locks链表上。如果是超期锁则设置锁的flag|=WAKE_LOCK_AUTO_EXPIRE,否则取消WAKE_LOCK_AUTO_EXPIRE标志。如果锁是WAKE_LOCK_SUSPEND型的,则继续下面的步骤。
4) 对于WAKE_LOCK_SUSPEND型的锁如果它是超期锁,则调用has_wake_lock_locked函数检查所有处于活动状态的WAKE_LOCK_SUSPEND锁(即在active_wake_locks链表上的WAKE_LOCK_SUSPEND锁,或者说当前被加锁了的WAKE_LOCK_SUSPEND锁),是否有超期锁已经过期,如果有则把过期超期锁从active_wake_locks上删除,挂到inactive_locks上。同时它还检查链表上有没有非超期锁,如果有则直接返回-1,否则它最终返回的是所有超期锁过期时间的最大值
5) 如果has_wake_lock_locked函数返回的是-1(表示当前活动锁有非超时锁)或者0(表示所有活动锁都是超时锁,且全已经超时),则删除expire_timer,并排队一个suspend工作到suspend_work_queue工作队列,最终系统会suspend。suspend函数完成suspend系统的任务,它是suspend_work这个工作的处理函数,suspend_workk排队到suspend_work_queue工作队列中,最终系统会处理这个work,调用其handler即suspend函数。该函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend()就会调用
enter_state()来进入 linux的suspend流程。
四、系统进入睡眠(suspend)
当按了MID上的power键,经过一系统列的事务处理后,它会调用到PowerManager类中的goToSleep。在用户态的调用流程如下所示:
PowerManager.goToSleep(long time)-> PowerManagerService.goToSleep(long time)-> PowerManagerService.goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER)-> PowerManagerService.goToSleepLocked(long time, int reason)-> PowerManagerService.setPowerState(SCREEN_OFF, false, reason)-> PowerManagerService.sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER) PowerManagerService.setScreenStateLocked(true)-> Power.setScreenState-> android_os_Power.cpp::setScreenState-> Power.c::set_screen_state(int on)-> write(g_fds[REQUEST_STATE], buf, len)
上面的write将把"mem"写入/sys/power/state中。接下来,在kernel态,state_store函数将被调用。
• Android特有的earlysuspend: request_suspend_state(state)
• Linux标准的suspend: enter_state(state)
在state_store中,若定义了CONFIG_EARLYSUSPEND,则执行request_suspend_state(state)以先进入earlysuspend,然后根据wake_lock的状态决定是否进入suspend;否则直接执行enter_state(state)以进入suspend状态。
相关文章推荐
- Android睡眠唤醒机制--系统架构
- Android睡眠唤醒机制--系统架构
- Android睡眠唤醒机制--系统架构
- Android睡眠唤醒机制--系统架构
- Android睡眠唤醒机制--系统架构
- Android 系统电话管理机制与架构
- Android/linux(earlysuspend、lateresume)睡眠唤醒机制简介
- Android睡眠唤醒机制--Kernel态
- Android/linux(earlysuspend、lateresume)睡眠唤醒机制简介
- Android/linux(earlysuspend、lateresume)睡眠唤醒机制简介
- android4.4.4睡眠唤醒软件架构
- Android/linux(earlysuspend、lateresume)睡眠唤醒机制简介
- Android睡眠唤醒机制--Kernel态
- Android睡眠唤醒机制--HAL-->Kernel
- Android/linux(earlysuspend、lateresume)睡眠唤醒机制简介
- Android睡眠唤醒机制--Kernel态
- Android/linux(earlysuspend、lateresume)睡眠唤醒机制简介