android休眠与唤醒驱动流程分析
【推荐下载】Android 如何自动测试 睡眠和唤醒

Android 如何自动测试睡眠和唤醒2013/09/10 12 1.Android 平台,目的是测试内核及驱动在睡眠和唤醒过程中的健壮性。
2.(深度)睡眠(不仅仅是early_suspend)和唤醒之间自动切换,循环运行。
3.Android 闹钟app 也可以做这个测试,但这个不适合自动测试(鄙人观点)。
4.测试要求只有在测试开始的时候进行一次交互,可以设置测试的循环次数(实现自动化)。
5.测试要求2 次循环之间的间隔(最好)达到最小(提高测试效率)。
6.不使用电话,wifi 等外部唤醒(降低测试成本)。
7.测试要求不修改系统本身的源代码(实现跨平台测试)。
关键点: 1.如何快速使系统进入深度睡眠。
2.如何定时让睡眠中的系统唤醒。
3.如何循环以上步骤1 和2。
提醒: 1.鄙人的思路是借助系统的Alarm(RTC)机制。
2.您在测试的时候别忘了拔掉USB 线,否则系统不会深度睡眠。
问题: 1.在终端使用脚本实现这个测试的可行性?如果可行,如何实现? 2.使用javaapp 实现这个测试的可行性?如果可行,如何实现? 3.您认为(深度)睡眠和唤醒应该如何测试? 4.乐于倾听您任何失败和成功的经验! 5.任何您看到这个帖子想说的!目前只知道灭屏后系统会休眠,但不是深度睡眠,一般都要十几分钟后才会进入深度睡眠,但是不晓得如何得知系统已经进入深度睡眠?测试是否深度睡眠其实可以通过测试电流来确定一般机子睡眠的时候电流不超过10ma 还有如何判断睡眠和深度睡眠android 里面有个wakelock。
这个东西你可以百度一下。
深度睡眠就是那种电流不超过10ma 的情况,至于非深度睡眠。
驱动里面有个early_suspendsuspend(睡眠) 当你点击power 的时候,early_suspend 的器件会进入休眠状态,也就是不工作,没有电流。
而suspend 的器件会检测这个wakelock,如果锁住的即不进入休眠状态,也就是非深度睡眠,如果没有锁住,该器件也睡眠,就进入了深度睡眠。
android的休眠和唤醒

android休眠与唤醒驱动流程分析标准linux休眠过程:●power management notifiers are executed with PM_SUSPEND_PREPARE●tasks are frozen●target system sleep state is announced to the platform-handling code●devices are suspended●platform-specific global suspend preparation methods are executed●non-boot CPUs are taken off-line●interrupts are disabled on the remaining (main) CPU●late suspend of devices is carried out (一般有一些BUS driver的动作进行)●platform-specific global methods are invoked to put the system to sleep标准linux唤醒过程:●t he main CPU is switched to the appropriate mode, if necessary●early resume of devices is carried out (一般有一些BUS driver的动作进行)●interrupts are enabled on the main CPU●non-boot CPUs are enabled●platform-specific global resume preparation methods are invoked●devices are woken up●tasks are thawed●power management notifiers are executed with PM_POST_SUSPEND用户可以通过sys文件系统控制系统进入休眠:查看系统支持的休眠方式:#cat /sys/power/state常见有standby(suspend to RAM)、mem(suspend to RAM)和disk(suspend to disk),只是standby耗电更多,返回到正常工作状态的时间更短。
android电源管理wakelock唤醒锁机制

android电源管理wakelock唤醒锁机制转载Android 电源管理—唤醒锁全新上市大多数人可能都遭遇过手机的电池续航时间较短带来的尴尬。
这极其令人讨厌。
没电的手机和一块水泥砖没什么差别。
一般而言,如果用户的手机电池无法持续一整天,他们会感到非常不满。
而且,当手机充电时用户无法使用手机,这同样会带来极大的不便。
传统上需要使用笔记本电脑或 PC 处理的任务,现在借助全新的改进软件,即使未在桌旁也可使用智能手机进行处理。
但是相比笔记本电脑,智能手机的小外形很大地限制了可容纳的电池尺寸。
既要求手机具备笔记本电脑的功能,同时又要求其具备全天候的电池续航能力是难以实现的。
通过采用出色的电源管理,Android和其他移动操作系统实现了耐久的电池续航时间。
停止使用手机后不久,显示器便会关闭,CPU 会进入深度节能状态,因此在不使用它时仅会消耗极少的电源。
这就是电话在使用时充一次电便能持续使用多日的原因。
借助android的电源管理器,正常计划是显示器关闭时 CPU 也关闭。
但是,Android 开发人员能够(并有权限)阻止 Android 设备进入睡眠模式。
他们可能希望让 CPU 处于活动状态—即使显示器关闭。
或者可能他们希望在执行某项活动时阻止显示器自动关闭。
出于此原因,Google* 在其 PowerManager API 中增加了唤醒锁。
阻止设备进入睡眠模式的应用可以使用唤醒锁。
只要系统上有活动的唤醒锁,设备便无法进入挂起模式,除非释放唤醒锁。
使用唤醒锁时,一定要了解到当您不需要唤醒锁时,必须将其正确释放,因为未释放的唤醒锁无法进入默认状态以节能,从而很快便会将设备的电池耗尽。
本文将会为您介绍一些在Android 4.0 中默认使用唤醒锁的Android 应用(和使用模式),以便帮助您了解何时使用此项技术。
然后,将会介绍一个 SDPSamples 集中的示例应用“Wakelocks”,以展示如何编写唤醒锁的代码。
android休眠唤醒流程2

android休眠唤醒流程2android系统⼀段时间没有操作,屏幕(screen)将从⾼亮(bright)变为暗淡(dim),如果再过段时间还是没有操作,屏幕(screen)从暗淡(dim)变为关闭(off).这时,系统将进⼊休眠.⽽对于某些需要保持系统唤醒甚⾄屏幕唤醒的应⽤(⽐如视频播放器和⾳乐播放器)来说,就必须要有⼀个机制,使得系统不进⼊休眠状态,设置保持屏幕亮屏状态.wakelock即⽤来实现以上⽬的先上⽹上偷来的⼀副图,说⼀下android系统的整个电源管理流程图接下来对每⼀个模块具体分析:powermanager对应⽂件是android/frameworks/base/core/java/android/os/PowerManager.java在Android中应⽤程序并不是直接同PowerManagerService交互的,⽽是通过PowerManager间接地与PowerManagerService打交道。
此⽂件定义了⼀个powermanager类.主要实现了1,wakelock的申请与释放public WakeLock newWakeLock(int flags, String tag)2,系统延时进⼊休眠public void userActivity(long when, boolean noChangeLights)3,系统强制休眠public void goToSleep(long time)4,屏幕亮度设置public void setBacklightBrightness(int brightness)5,屏幕状态查询public boolean isScreenOn()6,系统重启public void reboot(String reason)细节wakelock的申请与释放{@samplecode*PowerManager pm = (PowerManager)mContext.getSystemService(* Context.POWER_SERVICE);*PowerManager.WakeLock wl = pm.newWakeLock(* PowerManager.SCREEN_DIM_WAKE_LOCK* | PowerManager.ON_AFTER_RELEASE,* TAG);*wl.acquire();* // ...*wl.release();⼀共有如下⼏个flag来进⾏不⼀样的唤醒⽅式.可以根据需要设置Flag Value CPU Screen KeyboardPARTIAL_WAKE_LOCK On* can-off OffSCREEN_DIM_WAKE_LOCK On Dim OffPROXIMITY_SCREEN_OFF_WAKE_LOCK on 距离传感器时关闭 offSCREEN_BRIGHT_WAKE_LOCK On Bright OffFULL_WAKE_LOCK On Bright BrightACQUIRE_CAUSES_WAKEUP 确保wakelock,主要⽤于视频播放器ON_AFTER_RELEASE = 0x20000000 release后倒计时,关闭屏幕...userActivity的作⽤:使系统从其他状态进⼊全部打开状态,⽐如从暗屏(dim)切换到亮屏,并重置倒计时计数器(待续)。
【Android休眠】之休眠锁的获取和释放

【Android休眠】之休眠锁的获取和释放一、PowerManagerService引起休眠动作(进入休眠前执行一些必要的操作)的事件有两个:PowerKey事件,通过JNI调用PowerManagerService中的goToSleepFromNative()方法Timeout,指【设置->显示->休眠】中设置的Timeout数值Android休眠在PowerManagerService中的流程如下图:图示:最终都会调用到updatePowerStateLocked()方法,在更新一些标志的状态、发送休眠通知后,调用updateSuspendBlockerLocked()执行休眠锁的释放动作。
二、PowerManagerService中Timeout处理流程1./**2.* PowerManagerService设置了很多的标志位,用来标识某个事件的状态是否发生改变,比如:3.* DIRTY_SETTINGS,一旦系统设置发生变化,DIRTY_SETTINGS位就会被设置,4.* 处理函数检测到DIRTY_SETTINGS被置位,就进行相应的动作5.* dirty:包含了所有发生变化的标志6.*/7.private void updateUserActivitySummaryLocked(long now, int dirty) {8.// Update the status of the user activity timeout timer.9.if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {10.// 1、消息队列中含有尚未处理的MSG_USER_ACTIVITY_TIMEOUT,就移除,避免重复进入休眠操作11.mHandler.removeMessages(MSG_USER_ACTIVITY _TIMEOUT);12.13.long nextTimeout = 0;14.// 2、mWakefulness != WAKEFULNESS_ASLEEP:当前醒着15.if (mWakefulness != WAKEFULNESS_ASLEEP) {16.// 3、获取Timeout的值,比如30s17.final int screenOffTimeout = getScreenOffTimeoutLocked();18.// 屏幕在熄灭前,会先变暗一段时间,这段时间叫DimDuration,计算方式:19.// SCREEN_DIM_DURATION = 7s,MAXIMUM_SCREEN_DIM_RATIO = 0.220.// Math.min(SCREEN_DIM_DURATION, (int)(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO))21.// 4、获取DimDuration的值,30s x 0.2 = 6s22.final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);23.24.mUserActivitySummary = 0;25.// 5、mLastUserActivityTime >= mLastWakeTime:用户最后使用机器的时间在上次唤醒时间之后26.if (mLastUserActivityTime >= mLastWakeTime) {27.// nextTimeout:此处指到屏幕Dim的时间间隔28.// 6、nextTimeout的时间:BASE + 30 - 6 = BASE + 2429.nextTimeout = mLastUserActivityTime30.+ screenOffTimeout - screenDimDuration;31.if (now < nextTimeout) {32.// now在屏幕Dim之前,说明屏幕亮着,设置flag33.mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;34.} else {35.// extTimeout:此处指到屏幕熄灭的时间间隔36.//7、nextTimeout的时间:BASE + 30 = BASE + 3037.nextTimeout = mLastUserActivityTime + screenOffTimeout;38.// 8、now处于屏幕Dim之后、屏幕熄灭之前设置DIM flag39.if (now < nextTimeout) {40.mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;41.}42.}43.}44.if (mUserActivitySummary == 045.&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {46.nextTimeout =mLastUserActivityTimeNoChangeLights + screenOffTimeout;47.if (now < nextTimeout48.&& mDisplayPowerRequest.screenState49.!= DisplayPowerRequest.SCREEN_STATE_OFF) {50.mUserActivitySummary = mDisplayPowerRequest.screenState51.== DisplayPowerRequest.SCREEN_STATE_BRIGHT ?ER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;53.}54.}55.// mUserActivitySummary发生了改变56.if (mUserActivitySummary != 0) {57.Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);58.Slog.i(TAG, "updateUserActivitySummaryLocked, send MSG_USER_ACTIVITY_TIMEOUT");59.msg.setAsynchronous(true);60.mHandler.sendMessageAtTime(msg, nextTimeout);61.}62.} else {63.mUserActivitySummary = 0;64.}65.}66.}67.68.69.MSG_USER_ACTIVITY_TIMEOUT事件处理:70.71.private final class PowerManagerHandler extends Handler {72.@Override73.public void handleMessage(Message msg) {74.switch (msg.what) {75.case MSG_USER_ACTIVITY_TIMEOUT:76.handleUserActivityTimeout();77.break;78.}79.}80.81./**82.* Called when a user activity timeout has occurred.83.* Simply indicates that something about user activity has changed so that the new84.* state can be recomputed when the power state is updated.85.*/86.private void handleUserActivityTimeout() { // runs on handler thread87.mDirty |= DIRTY_USER_ACTIVITY;88.updatePowerStateLocked();89.}90.91.92.三、PowerManagerService中休眠锁的获取/释放93.这部分代码清晰,直接看下:94.95.private void updatePowerStateLocked() {96.if (!mSystemReady || mDirty == 0) {97.return;98.}99.// Phase 0: Basic state updates.100.101.// Phase 1: Update wakefulness.102.103.// Phase 2: Update dreams and display power state.104.105.// Phase 3: Send notifications, if needed.106.107.// Phase 4: Update suspend blocker.108.// Because we might release the last suspend blocker here, we need to make sure109.// we finished everything else first!110.updateSuspendBlockerLocked();111.}112.113./**114.* Updates the suspend blocker that keeps the CPU alive.115.*/116.private void updateSuspendBlockerLocked() {117.final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);118.final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();119.120.// First acquire suspend blockers if needed.121.if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {122.mWakeLockSuspendBlocker.acquire();123.mHoldingWakeLockSuspendBlocker = true;124.}125.if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {126.mDisplaySuspendBlocker.acquire();127.mHoldingDisplaySuspendBlocker = true;128.}129.130.// Then release suspend blockers if needed.131.if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {132.mWakeLockSuspendBlocker.release();133.mHoldingWakeLockSuspendBlocker = false;134.}135.if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {136.mDisplaySuspendBlocker.release();137.mHoldingDisplaySuspendBlocker = false;138.}139.}140.141.private final class SuspendBlockerImpl implements SuspendBlocker {142.private final String mName;143.private int mReferenceCount;144.145.public SuspendBlockerImpl(String name) {146.mName = name;147.}148.149.@Override150.public void acquire() {151.synchronized (this) {152.mReferenceCount += 1;153.if (mReferenceCount == 1) {154.nativeAcquireSuspendBlocker(mName);155.}156.}157.}158.159.@Override160.public void release() {161.synchronized (this) {162.mReferenceCount -= 1;163.if (mReferenceCount == 0) {164.165.nativeReleaseSuspendBlocker(mName);166.}167.}168.}169.}170.171.休眠锁的获取和释放,最终通过JNI方式读写/sys/power/wake_lock、/sys/power/wake_unlock:172.173.// 1、JNI接口_android_server_power_PowerManagerServic e.cpp (frameworks\base\services\jni)175.static void nativeAcquireSuspendBlocker(JNIEnv*env, jclass clazz, jstring nameStr) {176.ScopedUtfChars name(env, nameStr);177.acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());178.}179.180.// 2、定义要操作的文件181.power.c (hardware\libhardware_legacy\power)182.const char * const NEW_PATHS[] = {183."/sys/power/wake_lock",184."/sys/power/wake_unlock",185.};186.187.// 3、初始化设备节点188.static inline void initialize_fds(void)189.{190.if (g_initialized == 0) {191.if(open_file_descriptors(NEW_PATHS) < 0)192.open_file_descriptors(OLD_PATHS);193.g_initialized = 1;194.}195.}196.197.static int open_file_descriptors(const char * const paths[])198.{199.int i;200.for (i=0; i<OUR_FD_COUNT; i++) {201.int fd = open(paths[i], O_RDWR);202.if (fd < 0) {203.fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);204.g_error = errno;205.return -1;206.}207.g_fds[i] = fd;208.}209.210.g_error = 0;211.return 0;212.}213.214.// 4、id即为锁的名字,之后就是读写设备215.int acquire_wake_lock(int lock, const char* id)216.{217.initialize_fds();218.219.if (g_error) return g_error;220.221.int fd;222.223.if (lock == PARTIAL_WAKE_LOCK) {224.fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];225.}226.else {227.return EINVAL;228.}229.230.return write(fd, id, strlen(id));231.}232.MSG_USER_ACTIVITY_TIMEOUT事件处理:1.private final class PowerManagerHandler extends Handler {2.@Override3.public void handleMessage(Message msg) {4.switch (msg.what) {5.case MSG_USER_ACTIVITY_TIMEOUT:6.handleUserActivityTimeout();7.break;8.}9.}10.11./**12.* Called when a user activity timeout has occurred.13.* Simply indicates that something about user activity has changed so that the new14.* state can be recomputed when the power state is updated.15.*/16.private void handleUserActivityTimeout() { // runs on handler thread17.mDirty |= DIRTY_USER_ACTIVITY;18.updatePowerStateLocked();19.}三、PowerManagerService中休眠锁的获取/释放这部分代码清晰,直接看下:1.private void updatePowerStateLocked() {2.if (!mSystemReady || mDirty == 0) {3.return;4.}5.// Phase 0: Basic state updates.6.7.// Phase 1: Update wakefulness.8.9.// Phase 2: Update dreams and display power state.10.11.// Phase 3: Send notifications, if needed.12.13.// Phase 4: Update suspend blocker.14.// Because we might release the last suspend blocker here, we need to make sure15.// we finished everything else first!16.updateSuspendBlockerLocked();17.}18.19./**20.* Updates the suspend blocker that keeps the CPU alive.21.*/22.private void updateSuspendBlockerLocked() {23.final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);24.final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();25.26.// First acquire suspend blockers if needed.27.if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {28.mWakeLockSuspendBlocker.acquire();29.mHoldingWakeLockSuspendBlocker = true;30.}31.if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {32.mDisplaySuspendBlocker.acquire();33.mHoldingDisplaySuspendBlocker = true;34.}35.36.// Then release suspend blockers if needed.37.if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {38.mWakeLockSuspendBlocker.release();39.mHoldingWakeLockSuspendBlocker = false;40.}41.if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {42.mDisplaySuspendBlocker.release();43.mHoldingDisplaySuspendBlocker = false;44.}45.}46.47.private final class SuspendBlockerImpl implements SuspendBlocker {48.private final String mName;49.private int mReferenceCount;50.51.public SuspendBlockerImpl(String name) {52.mName = name;53.}54.55.@Override56.public void acquire() {57.synchronized (this) {58.mReferenceCount += 1;59.if (mReferenceCount == 1) {60.nativeAcquireSuspendBlocker(mName);61.}62.}63.}64.65.@Override66.public void release() {67.synchronized (this) {68.mReferenceCount -= 1;69.if (mReferenceCount == 0) {70.71.nativeReleaseSuspendBlocker(mName);72.}73.}74.}75.}休眠锁的获取和释放,最终通过JNI方式读写/sys/power/wake_lock、/sys/power/wake_unlock:1.// 1、JNI接口_android_server_power_PowerManagerService.cpp (frameworks\base\services\jni)3.static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {4.ScopedUtfChars name(env, nameStr);5.acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());6.}7.8.// 2、定义要操作的文件9.power.c (hardware\libhardware_legacy\power)10.const char * const NEW_PATHS[] = {11."/sys/power/wake_lock",12."/sys/power/wake_unlock",13.};14.15.// 3、初始化设备节点16.static inline void initialize_fds(void)17.{18.if (g_initialized == 0) {19.if(open_file_descriptors(NEW_PATHS) < 0)20.open_file_descriptors(OLD_PATHS);21.g_initialized = 1;22.}23.}24.25.static int open_file_descriptors(const char * const paths[])26.{27.int i;28.for (i=0; i<OUR_FD_COUNT; i++) {29.int fd = open(paths[i], O_RDWR);30.if (fd < 0) {31.fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);32.g_error = errno;33.return -1;34.}35.g_fds[i] = fd;36.}37.38.g_error = 0;39.return 0;40.}41.42.// 4、id即为锁的名字,之后就是读写设备43.int acquire_wake_lock(int lock, const char* id)44.{45.initialize_fds();46.47.if (g_error) return g_error;48.49.int fd;50.51.if (lock == PARTIAL_WAKE_LOCK) {52.fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];53.}54.else {55.return EINVAL;56.}57.58.return write(fd, id, strlen(id));59.}。
Android的休眠与唤醒(转)

Android的休眠与唤醒(转)Android 休眠(suspend),在一个打过android补丁的内核中,state_store()函数会走另外一条路,会进入到request_suspend_state()中,这个文件在earlysuspend.c中。
这些功能都是android系统加的,后面会对 earlysuspend和late resume 进行介绍。
涉及到的文件:linux_source/kernel/power/main.clinux_source/kernel/power/earlysuspend.clinux_source/kernel/power/wakelock.c(1)特性介绍Early Suspend:Early suspend 是android 引进的一种机制,这种机制在上游备受争议,这里不做评论。
这个机制作用在关闭显示的时候。
一些和显示有关的设备,比如LCD背光,比如重力感应器、触摸屏、这些设备都会关掉。
但是系统可能还是在运行状态(这时候还有wake lock)进行任务的处理,例如在扫描SD卡上的文件等。
在嵌入式设备中,背光是一个很大的电源消耗,所以android会加入这样一种机制。
Late Resume:Late Resume 是和suspend 配套的一种机制,是在内核唤醒完毕开始执行的。
主要就是唤醒在Early Suspend的时候休眠的设备。
Wake Lock:Wake Lock 在Android的电源管理系统中扮演一个核心的角色。
Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得。
这个锁可以是有超时的或者是没有超时的,超时的锁会在时间过去以后自动解锁。
如果没有锁了或者超时了,内核就会启动休眠的那套机制来进入休眠。
(2)过程A,Android Suspend,当用户写入mem 或者standby到/sys/power/state中的时候,state_store()会被调用,然后Android 会在这里调用 request_suspend_state(),而标准的Linux会在这里进入enter_state()这个函数。
android睡眠唤醒调试

android睡眠唤醒调试1:early_suspend late_resume添加log在earlysuspend.c中static int debug_mask = DEBUG_USER_STATE;->static int debug_mask = DEBUG_USER_STATE | DEBUG_SUSPEND |DEBUG_VERBOSE;就可以打印出对应的设备。
2:resume suspend debug在platform.c(driver/base)中添加log,打印相应设备:int platform_pm_suspend(struct device *dev){struct device_driver *drv = dev->driver;int ret = 0;if (!drv)return 0;if (drv->pm) {if (drv->pm->suspend)ret = drv->pm->suspend(dev);+printk("%s called name = %s\n",__func__,drv->name);} else {ret = platform_legacy_suspend(dev, PMSG_SUSPEND);}return ret;}int platform_pm_resume(struct device *dev){struct device_driver *drv = dev->driver;int ret = 0;if (!drv)return 0;if (drv->pm) {if (drv->pm->resume)ret = drv->pm->resume(dev);+printk("%s called name = %s\n",__func__,drv->name);} else {ret = platform_legacy_resume(dev);}return ret;}log:<6>[ 53.643766] request_suspend_state: sleep (0->3) at 53636581667(1970-01-02 08:21:01.108440452 UTC)<6>[ 53.651854] early_suspend: call handlers<6>[ 53.655669] early_suspend: calling ft5x06_ts_early_suspend<6>[ 53.663818] early_suspend: calling stop_drawing_early_suspend<6>[ 53.682527] early_suspend: calling kgsl_early_suspend_driver<6>[ 53.687166] early_suspend: calling msmfb_early_suspend<6>[ 53.748298] msm_hsic_host msm_hsic_host: HSIC-USB exited from lowpower mode<3>[ 53.757271] mdp4_mixer_blend_setup: Error: no bg_pipe at mixer=0<4>[ 53.762276] mipi_sharp_lcd_off<6>[ 53.921562] mipi_dsi_lms_panel_power: on=0<6>[ 53.926171] early_suspend: calling msmfb_early_suspend<6>[ 53.930749] early_suspend: calling mdp_early_suspend<3>[ 53.935235] dtv_pipe is not configured yet<6>[ 53.951716] early_suspend: calling msmsdcc_early_suspend<6>[ 53.955989] early_suspend: calling msmsdcc_early_suspend<6>[ 53.961819] PM: Syncing filesystems...<6>[ 53.966061] sync done.<6>[ 53.967404] active wake lock msm_hsic_host<6>[ 53.971463] active wake lock PowerManagerService<6>[ 55.280024] msm_hsic_host msm_hsic_host: HSIC-USB in low powermode<6>[ 55.425301] msm_hsic_host msm_hsic_host: HSIC-USB exited from lowpower mode<6>[ 57.269342] msm_hsic_host msm_hsic_host: HSIC-USB in low powermode<6>[ 58.209522] suspend: enter suspend<6>[ 58.211963] PM: suspend entry 1970-01-02 08:21:05.676635122 UTC<6>[ 58.217945] PM: Syncing filesystems...<6>[ 58.225911] sync done.<6>[ 58.227468] PM: Syncing filesystems...<6>[ 58.232992] sync done.<4>[ 58.234640] Freezing user space processes ... (elapsed 0.04seconds) done.<4>[ 58.283076] Freezing remaining freezable tasks ... (elapsed 0.02seconds) done.<4>[ 58.312711] Suspending console(s) (use no_console_suspend todebug)<4>[ 58.330901] platform_pm_suspend called name = diag_bridge<4>[ 58.331634] platform_pm_suspend called name = msm_hsic_host<4>[ 58.331725] platform_pm_suspend called name = DIAG<4>[ 58.331756] platform_pm_suspend called name =DIAG_CNTL<4>[ 58.331909] platform_pm_suspend called name = APPS_RIVA_DATA<4>[ 58.331970] platform_pm_suspend called name = APPS_RIVA_CTRL<4>[ 58.333984] platform_pm_suspend called name = soc-audio<4>[ 58.335876] PM_DEBUG_MXP:set max sleep time diff=1796.<6>[ 58.335907] msm_pm_set_max_sleep_time: Requested 1796000000000 nsGiving 58852442 sclk ticks<4>[ 58.337494] platform_pm_suspend called name = tabla_codec<4>[ 58.338806] platform_pm_suspend called name = msm_fb<4>[ 58.338837] platform_pm_suspend called name = mdp<6>[ 58.338989] msm_fb_ext_suspend: Turning off HPD circuitry<4>[ 58.339203] platform_pm_suspend called name = msm_fb<4>[ 58.339264] platform_pm_suspend called name = mdp<4>[ 58.339294] platform_pm_suspend called name = dtv<4>[ 58.339417] platform_pm_suspend called name = msm_fb<4>[ 58.339447] platform_pm_suspend called name = mdp<4>[ 58.343506] tsl2771_suspend Called<4>[ 58.343842] platform_pm_suspend called name = gpio-keys<4>[ 58.344269] platform_pm_suspend called name = kgsl-3d<4>[ 58.344300] platform_pm_suspend called name = dtv<4>[ 58.344391] platform_pm_suspend called name = mdp<4>[ 58.344544] platform_pm_suspend called name = msm_fb<4>[ 58.345246] platform_pm_suspend called name = msm_serial_hsl<4>[ 58.345338] platform_pm_suspend called name = msm_slim_ctrl<4>[ 58.346528] platform_pm_suspend called name = msm_sdcc<4>[ 58.346589] platform_pm_suspend called name = msm_sdcc<4>[ 58.346680] platform_pm_suspend called name = qup_i2c<4>[ 58.346772] platform_pm_suspend called name = qup_i2c<4>[ 58.346864] platform_pm_suspend called name = qup_i2c<4>[ 58.346955] platform_pm_suspend called name = qup_i2c<4>[ 58.347047] platform_pm_suspend called name = tsens8960-tm<4>[ 58.347565] platform_pm_suspend called name = msm_vidc<4>[ 58.348695] platform_pm_suspend called name = msm_watchdog<4>[ 58.348817] platform_pm_suspend called name = wcnss_wlan<4>[ 58.348878] platform_pm_suspend called name =msm_hsusb_host<4>[ 58.348939] platform_pm_suspend called name = msm_otg<4>[ 58.349214] platform_pm_suspend called name = pm8xxx-vib<4>[ 58.349336] platform_pm_suspend called name = pm8xxx-tm<4>[ 58.349580] platform_pm_suspend called name = pm8xxx-adc<4>[ 58.349641] platform_pm_suspend called name = pm8921-charger<4>[ 58.349702] platform_pm_suspend called name = pm8xxx-pwrkey<4>[ 58.349763] platform_pm_suspend called name = rtc-pm8xxx<4>[ 58.350099] platform_pm_suspend called name = msm_dmov<4>[ 58.351045] platform_pm_suspend called name = power<6>[ 58.351472] PM: suspend of devices complete after 23.775 msecs<6>[ 58.355226] PM: late suspend of devices complete after 3.692 msecs<6>[ 58.363528] power_suspend_late return 0<6>[ 58.363558] PM: noirq suspend of devices complete after 8.301msecs<4>[ 58.363589] Disabling non-boot CPUs ...<6>[ 58.364474] msm_pm_enter<6>[ 58.364474] msm_pm_enter: power collapse<6>[ 58.364474] msm_mpm_irqs_detectable: cannot monitor000000,00000000,00000000,00000000,00000000,00000020, 00000000,00000000,00000000,00000000,00000000,00000000,0 0008000,00000000<6>[ 58.364474] msm_pm_enter: return<6>[ 58.371738] PM: noirq resume of devices complete after 6.470 msecs<6>[ 58.375064] wakeup wake lock: event2-624<6>[ 58.379337] PM: early resume of devices complete after 3.905msecs //<4>[ 58.381748] platform_pm_resume called name = power<4>[ 58.382267] platform_pm_resume called name = msm_dmov<4>[ 58.382450] platform_pm_resume called name = rtc-pm8xxx<4>[ 58.382481] platform_pm_resume called name = pm8xxx-pwrkey<4>[ 58.382542] platform_pm_resume called name = pm8921-charger<4>[ 58.382572] platform_pm_resume called name = pm8xxx-adc<4>[ 58.382694] platform_pm_resume called name = pm8xxx-tm<4>[ 58.382755] platform_pm_resume called name = pm8xxx-vib<4>[ 58.382908] platform_pm_resume called name = msm_otgmsm_hsusb_host<4>[ 58.383000] platform_pm_resume called name = wcnss_wlan<4>[ 58.383061] platform_pm_resume called name = msm_watchdog<4>[ 58.383732] platform_pm_resume called name = msm_vidc<4>[ 58.384037] platform_pm_resume called name = tsens8960-tm<4>[ 58.384129] platform_pm_resume called name = qup_i2c<4>[ 58.384190] platform_pm_resume called name = qup_i2c<4>[ 58.384251] platform_pm_resume called name = qup_i2c<4>[ 58.384312] platform_pm_resume called name = qup_i2c<4>[ 58.384373] platform_pm_resume called name = msm_sdcc<4>[ 58.384404] platform_pm_resume called name = msm_sdcc<4>[ 58.384434] platform_pm_resume called name = msm_slim_ctrl<4>[ 58.385319] platform_pm_resume called name = msm_serial_hsl<4>[ 58.385380] platform_pm_resume called name = msm_fb<4>[ 58.385472] platform_pm_resume called name = mdp<4>[ 58.385533] platform_pm_resume called name = dtv3d<4>[ 58.385869] platform_pm_resume called name = gpio-keys<4>[ 58.386082] tsl2771_resume called<4>[ 58.388921] platform_pm_resume called name = mdp<4>[ 58.388951] platform_pm_resume called name = msm_fb<4>[ 58.389012] platform_pm_resume called name = dtv<4>[ 58.389043] platform_pm_resume called name = mdp<6>[ 58.389256] msm_fb_ext_resume: Turning on HPD circuitry<4>[ 58.389287] platform_pm_resume called name = msm_fb<4>[ 58.389378] platform_pm_resume called name = mdp<4>[ 58.389409] platform_pm_resume called name = msm_fb<4>[ 58.390172] platform_pm_resume called name = tabla_codec<4>[ 58.392675] platform_pm_resume called name = soc-audio<4>[ 58.393834] platform_pm_resume called name = APPS_RIVA_CTRL<4>[ 58.393865] platform_pm_resume called name = APPS_RIVA_DATA<4>[ 58.393987] platform_pm_resume called name = DIAG_CNTL<4>[ 58.394017] platform_pm_resume called name = DIAG<4>[ 58.394109] platform_pm_resume called name = msm_hsic_host<4>[ 58.395757] platform_pm_resume called name = diag_bridge<6>[ 58.396184] PM: resume of devices complete after 16.836 msecs<4>[ 58.937524] PS/ALS power not enable<4>[ 58.940759] Restarting tasks ...<4>[ 58.960598] QSEECOM: qseecom_receive_req: Interrupted: exitingwait_rcv_req loop<3>[ 58.967190] QSEECOM: qseecom_ioctl: failed qseecom_receive_req:-512<4>[ 58.973630] QSEECOM: qseecom_receive_req: Interrupted: exitingwait_rcv_req loop<4>[ 58.986967] done.<3>[ 58.991301] QSEECOM: qseecom_ioctl: failed qseecom_receive_req:-512<6>[ 59.007294] PM: suspend exit 1970-01-02 08:21:08.615414069 UTC<6>[ 59.012482] suspend: exit suspend, ret = 0 (1970-01-0208:21:08.620600665 UTC)<6>[ 59.145154] request_suspend_state: wakeup (3->0) at 59137427297(1970-01-02 08:21:08.753199711 UTC)<6>[ 59.153425] late_resume: call handlers<6>[ 59.156966] late_resume: calling msmsdcc_late_resume<6>[ 59.170517] late_resume: calling msmsdcc_late_resume<6>[ 59.174576] late_resume: calling mdp_early_resume<6>[ 59.207569] late_resume: calling msmfb_early_resume<6>[ 59.215870] late_resume: calling msmfb_early_resume<6>[ 59.263787] mipi_dsi_lms_panel_power: on=1<4>[ 59.343323] mipi_sharp_lcd_on<6>[ 59.423164] msm_hsic_host msm_hsic_host: HSIC-USB exited from lowpower mode<6>[ 59.478345] late_resume: calling kgsl_late_resume_driver<6>[ 59.482923] late_resume: calling start_drawing_late_resume<6>[ 59.494277] late_resume: calling ft5x06_ts_late_resume<4>[ 59.498702] Set RESET: 0<4>[ 59.552021] Set RESET: 1<6>[ 59.553547] late_resume: done<0>[ 59.579551] ALS average: 28mipi_set_backlight level =25.。
Android Linux的休眠和唤醒

Android Linux的休眠和唤醒Android下有三种省电方式:Early_suspend::主要是屏幕省电需要。
进入early_suspend后,注册了early_suspend的外设进入休眠,大部分进程都还在运行,CPU处于正常工作状态。
外设可以通过register_early_suspend注册为early_suspend设备。
LPAUDION_MODE:系统进入early_suspend模式之后,通过has_audio_wake_lock判断是否进入LPAUDION_MODE模式,进入LPAUDION_MODE后,音乐正常播放,CPU进入省电模式。
Suspend:系统运行状态保存到内存,CPU进入省电模式,所有外设电源关闭,只有内存保持供电和工作。
跟休眠唤醒相关的文件:/kernel/power/main.c/kernel/power/earlysuspend.c/kernel/power/wakelock.c/kernel/power/suspend.c/drivers/base/power/main.c/arch/arm/plat-samsung/pm.c/arch/arm/mach-s5pv210/arch/arm/plat-s5p/sleep.s/arch/arm/mach-s5pv210/cpuidle.cAndroid linux休眠流程:休眠的入口在/kernel/power/main.c的state_store函数。
State_store函数通过power_attr(state)宏,在sysfs中定义了一个属性。
用户空间可以通过向state写入MEM,就可以使系统进入休眠状态。
也可以通过cat state查看支持哪些休眠方式在state_store函数中,调用request_suspend_state函数请求休眠。
在request_suspend_state 中,如果判断到系统不处于休眠状态,则调用early_suspend。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
android休眠与唤醒驱动流程分析标准linux休眠过程:●power management notifiers are executed with PM_SUSPEND_PREPARE●tasks are frozen●target system sleep state is announced to the platform-handling code●devices are suspended●platform-specific global suspend preparation methods are executed●non-boot CPUs are taken off-line●interrupts are disabled on the remaining (main) CPU●late suspend of devices is carried out (一般有一些BUS driver的动作进行)●platform-specific global methods are invoked to put the system to sleep标准linux唤醒过程:●t he main CPU is switched to the appropriate mode, if necessary●early resume of devices is carried out (一般有一些BUS driver的动作进行)●interrupts are enabled on the main CPU●non-boot CPUs are enabled●platform-specific global resume preparation methods are invoked●devices are woken up●tasks are thawed●power management notifiers are executed with PM_POST_SUSPEND用户可以通过sys文件系统控制系统进入休眠:查看系统支持的休眠方式:#cat /sys/power/state常见有standby(suspend to RAM)、mem(suspend to RAM)和disk(suspend to disk),只是standby耗电更多,返回到正常工作状态的时间更短。
通过#echo mem > /sys/power/state 让系统进入休眠。
Android休眠与唤醒android是在传统的linux内核电源管理设计的基础上,结合手机设计的实际需求而进化出的一套电源管理系统,其核心内容有:wakelock 、early_suspend与late_resume。
wakelock在Android的电源管理系统中扮演一个核心的角色。
wakelock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得。
这个锁可以是有超时的或者是没有超时的,超时的锁会在时间过去以后自动解锁。
如果没有锁了或者超时了,内核就会启动休眠的那套机制来进入休眠。
当系统在启动完毕后,会自己去加一把名为“main“的锁,而当系统有意愿去睡眠时则会先去释放这把“main”锁,在android中,在early_suspend的最后一步会去释放“main”锁(wake_unlock: main)。
释放完后则会去检查是否还有其他存在的锁,如果没有则直接进入睡眠过程。
它的缺点是,如果有某一应用获锁而不释放或者因一直在执行某种操作而没时间来释放的话,则会导致系统一直进入不了睡眠状态,功耗过大。
early_suspend:先与linux内核的睡眠过程被调用。
一般在手机系统的设计中对背光的操些在内核中要预先进行处理的事件可以先注册上early_suspend函数,当系统要进入睡眠之前会首先调用这些注册的函数。
本文中,linux kernel版本为linux-2.6.29,android版本为android 2.1与android休眠唤醒主要相关的文件主要有:●linux_source/kernel/power/main.c●linux_source/kernel/power/earlysuspend.c●linux_source/kernel/power/wakelock.c●linux_source/kernel/power/process.c●linux_source/driver/base/power/main.c●linux_source/arch/xxx/mach-xxx/pm.c或linux_source/arch/xxx/plat-xxx/pm.cAndroid 休眠过程如下:当用户读写/sys/power/state时,linux_source/kernel/power/main.c中的state_store()函数会被调用。
其中,android的early_suspend会执行request_suspend_state(state); 而标准的linux休眠则执行error = enter_state(state);static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n){#ifdef CONFIG_SUSPEND#ifdef CONFIG_EARL YSUSPENDsuspend_state_t state = PM_SUSPEND_ON;#elsesuspend_state_t state = PM_SUSPEND_STANDBY;#endifconst char * const *s;#endifchar *p;int len;int error = -EINV AL;p = memchr(buf, '\n', n);len = p ? p - buf : n;/* First, check if we are requested to hibernate */if (len == 4 && !strncmp(buf, "disk", len)) {error = hibernate();goto Exit;}#ifdef CONFIG_SUSPENDfor (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {if (*s && len == strlen(*s) && !strncmp(buf, *s, len))break;}if (state < PM_SUSPEND_MAX && *s)#ifdef CONFIG_EARL YSUSPENDif (state == PM_SUSPEND_ON || valid_state(state)) {error = 0;request_suspend_state(state);}#elseerror = enter_state(state);#endifExit:return error ? error : n;}在request_suspend_state(state)函数中,会调用early_suspend_work的工作队列,从而进入early_suspend()函数中。
static DECLARE_WORK(early_suspend_work, early_suspend);void request_suspend_state(suspend_state_t new_state){unsigned long irqflags;int old_sleep;spin_lock_irqsave(&state_lock, irqflags);old_sleep = state & SUSPEND_REQUESTED;if (debug_mask & DEBUG_USER_STA TE) {struct timespec ts;struct rtc_time tm;getnstimeofday(&ts);rtc_time_to_tm(_sec, &tm);pr_info("request_suspend_state: %s (%d->%d) at %lld ""(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",requested_suspend_state, new_state,ktime_to_ns(ktime_get()),tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,tm.tm_hour, tm.tm_min, tm.tm_sec, _nsec);}if (!old_sleep && new_state != PM_SUSPEND_ON) {state |= SUSPEND_REQUESTED;queue_work(suspend_work_queue, &early_suspend_work);} else if (old_sleep && new_state == PM_SUSPEND_ON) {state &= ~SUSPEND_REQUESTED;wake_lock(&main_wake_lock);queue_work(suspend_work_queue, &late_resume_work);}requested_suspend_state = new_state;spin_unlock_irqrestore(&state_lock, irqflags);}在early_suspend()函数中,首先要判断当前请求的状态是否还是suspend,若不是,则直接退出了;若是,函数会调用已经注册的early_suspend的函数。
然后同步文件系统,最后释放main_wake_lock。
static void early_suspend(struct work_struct *work){struct early_suspend *pos;unsigned long irqflags;int abort = 0;mutex_lock(&early_suspend_lock);spin_lock_irqsave(&state_lock, irqflags);if (state == SUSPEND_REQUESTED)state |= SUSPENDED;elseabort = 1;spin_unlock_irqrestore(&state_lock, irqflags);if (abort) {if (debug_mask & DEBUG_SUSPEND)pr_info("early_suspend: abort, state %d\n", state);mutex_unlock(&early_suspend_lock);goto abort;}if (debug_mask & DEBUG_SUSPEND)pr_info("early_suspend: call handlers\n");list_for_each_entry(pos, &early_suspend_handlers, link) {if (pos->suspend != NULL)pos->suspend(pos);}mutex_unlock(&early_suspend_lock);if (debug_mask & DEBUG_SUSPEND)pr_info("early_suspend: sync\n");sys_sync();abort:spin_lock_irqsave(&state_lock, irqflags);if (state == SUSPEND_REQUESTED_AND_SUSPENDED)wake_unlock(&main_wake_lock);spin_unlock_irqrestore(&state_lock, irqflags);}在wake_unlock()中,删除链表中wake_lock节点,判断当前是否存在wake_lock,若wake_lock的数目为0,则调用工作队列suspend_work,进入suspend状态。