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。
唤醒流程分析——Framework PowerMS分析过程
Internal Use
Check point
▪ 第5步时间长?
– 第5步,检查SCREEN_ON这个broadcast被所有的receiver执行 完的时间,用下面的log来判断
Copyright © MediaTek Inc. All rights reserved. 2014/5/20 13
Internal Use
典型例子:
▪ 例子3
– 按电源键,手机不能点屏幕
▪ 分析:
– 按前面的检查到了第5步:
– 在log中,并没有找到这行log:
01-01 00:02:11.234 522 539 D PowerManagerNotifier: finishPendingBroadcastLocked.
这两步之间时间长?请check 一下input 过程; 第一步时间长?请检查keyguard 的逻辑为何耗时; 第1步到第2步时间长?请检查framework Power逻辑为何耗时
第3步 第5步
第2步 第4步 第7步
第2步时间长?请检查keyguard逻辑为何耗时 第2步到第4步时间长? 请检查keyguard逻辑为何耗时 第4步到第7步时间长? 请检查keyguard逻辑为何耗时
Internal Use
亮屏慢
– 第6步,配合第3步来做分析
ห้องสมุดไป่ตู้检查 时长
– 第7步,检查keyguard在notifier后,整体ready的时长,用下面 的log来判断;
Copyright © MediaTek Inc. All rights reserved.
android的休眠和唤醒流程
android的休眠和唤醒流程android休眠唤醒流程:power按键事件上报给android系统,最终由windownmanager接收到,当有按键事件时判断是否需要休眠后唤醒系统,然后调⽤powermanager 系统服务去写/sys/power/state节点.此节点的写函数⾥判断收到的内容,来执⾏android的休眠early_suspend/唤醒late_resume流程.android层:private int setScreenStateLocked(boolean on) 电源管理服务:frameworks/base/services/java/com/android/server/PowerManagerService.javaint err = Power.setScreenState(on);在⽂件frameworks/base/core/java/android/os/Power.java定义79 public static native int setScreenState(boolean on);具体实现在:frameworks/base/core/jni/android_os_Power.cppstatic int setScreenState(JNIEnv *env, jobject clazz, jboolean on);set_screen_state(on); 在⽂件hardware/libhardware_legacy/power/power.c中定义并实现write(g_fds[REQUEST_STATE], buf, len); 写/sys/power/state节点内核层:向节点写内容会调⽤kernel/power/main.c的写函数:static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)request_suspend_state(state); 调⽤此函数: 具体实现在./kernel/power/earlysuspend.c中state: 为休眠则调⽤early_suspend_work android early_suspen⼯作队列为唤醒则调⽤late_resume_work android late_resume_work⼯作队列drivers/video/samsung/s3cfb_main.c中早已经注册屏幕开关register_early_suspend(&fbdev[i]->early_suspend);所以为休眠则调⽤early_suspend_work中的屏幕休眠函数:s3cfb_early_suspend()backlight_on()---->s3cfb_backlight_on() 在⽂件arch/arm/plat-s5p/dev-fimd-s5p.c中定义 npd->backlight_on = s3cfb_backlight_on;s3cfb_backlight_on中直接操作⽤来控制lcd的gpio关闭屏幕 arch/arm/mach-exynos/setup-fb-s5p.c为唤醒时调⽤late_resume_work中的屏幕唤醒函数:s3cfb_late_resume()backlight_off()---->s3cfb_backlight_off() 在⽂件arch/arm/plat-s5p/dev-fimd-s5p.c中定义 npd->backlight_off =s3cfb_backlight_off;s3cfb_backlight_off中直接操作⽤来控制lcd的gpio使能屏幕执⾏完所有的early_suspend后执⾏解锁main_wake_lock,以便休眠.wake_unlock(&main_wake_lock);mod_timer(&expire_timer, jiffies + has_lock); 在⽂件/kernel/power/wakelock.c中此函数将启⽤expire_timer定时器,定时器内容即expire_wake_locks340 static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);有四种⽅式可以引起休眠①在wake_unlock()中, 如果发现解锁以后没有任何其他的wake lock了, 就开始休眠②在定时器到时间以后, 定时器的回调函数会查看是否有其他的wake lock, 如果没有, 就在这⾥让系统进⼊睡眠③在wake_lock() 中, 对⼀个wake lock加锁以后, 会再次检查⼀下有没有锁, 刚加上锁,为什么要检查,有⽤吗④按power键,调⽤earlysuspend.使系统或应⽤程序释放锁.从⽽调⽤上述三个函数进⼊休眠if(has_lock ==0)queue_work(suspend_work_queue,&suspend_work); 由DECLARE_WORK(suspend_work, suspend);知道,队列中的内容即suspend 函数.suspend(); kernel/power/wakelock.cpm_suspend(requested_suspend_state);enter_state(state); kernel/power/suspend.csuspend_devices_and_enter(state);suspend_enter(state);suspend_ops->enter(state); -->调⽤平台相关的休眠函数,定义在中arch/arm/plat-samsung/pm.c:379:static const struct platform_suspend_ops s3c_pm_ops 即s3c_pm_enter s3c_pm_arch_stop_clocks() --> 休眠时执⾏的的最后⼀个函数.系统停在此处,等待中断或rtc等唤醒源唤醒.从此处开始唤醒流程enable_nonboot_cpus();suspend_test_start(); ---------->kernel已经被唤醒,当按键或中断来临后可以执⾏中断函数,上报唤醒事件.对于外部中断来说,上报power按键事件.pm_restore_gfp_mask(); kernel/power/suspend.center_state(state);pm_suspend(suspend_state_t state);suspend(); kernel/power/wakelock.c。
Android亮屏和熄屏控制实例详解
Android亮屏和熄屏控制实例详解本⽂实例讲述了Android亮屏和熄屏控制实现⽅法。
分享给⼤家供⼤家参考,具体如下:⼀、概述我们的Android应⽤程序很多需要和亮屏和熄屏打交道,⽐如闹钟的时候,需要保持亮屏,之后⼜需要熄屏。
那么今天,我们来分析下这⽅⾯的功能。
⼆. 系统服务 PowerManager.java顾名思义,PowerManager.java就是管理我们电源⽅⾯的功能的,当然也包括我们屏幕的亮和熄灭。
没错,我们的应⽤程序就是通过这个系统服务来实现亮屏和熄屏的功能的。
1. 应⽤程序获取PowerManager服务, 我们可以这样书写:复制代码代码如下:PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);因为PowerManager是系统服务,所以它的⽣命周期不是应⽤程序所能控制的;应⽤程序只能通过系统,向系统请求获取PowerManager服务,然后系统把这个服务的应⽤给我们。
2. goToSleep()⽅法,这个⽅法可以强制我们的屏幕熄屏。
我们可以这样调⽤:在上⾯拿到pm对象之后,这样调⽤pm.goToSleep(SystemClock.uptimeMillis());3. setBacklightBrightness()⽅法,这个⽅法可以设置背光的亮度,从0-255三. 定时熄灭屏幕那么这⾥,还可以介绍⼀个控制屏幕的⽅法就是PowerManager.WakeLock顾名思义,WakeLock这个东西就是亮屏控制,这⾥说的亮屏,它定义了⼏种类型的亮屏。
如下:类型cpu屏幕键盘PARTIAL_WAKE_LOCK on off offSCREEN_DIM_WAKE_LOCK on dim offSCREEN_BRIGHT_WAKE_LOCK on Bright offFULL_WAKE_LOCK on Bright Bright由于它定义了这么多类型,每种类型可以指定相对应的部件⼯作和不⼯作。
Androidlinux的休眠和唤醒
Androidlinux的休眠和唤醒写了很多内容,突然发布文章的时候保存失败。
郁闷凭借记忆只重写如下总结:1. Early suspend/ late resume 是android 添加的机制,用户关闭LCD, TS, Sensors等为了省电。
可称之为浅度休眠2. Linux的Suspend/resume 仍然有效,可称之为深度休眠3. echo mem > sys/power/state 会触发early suspend,echo on > sys/power/state 会触发late resume,cat sys/power/state 会显示当前支持的休眠状态,有mem, on, standby选项,但针对android 则只有mem, 同时无条件支持on4. LCD, TS, Sensors等设备会注册early suspend 和late resume 回调函数,用于early suspend/late resume时逐个执行。
5. User space 通过操作sys/power/wake_lock, sys/power/wake_unlock 可以向kernel申请一个wake lock;cat sys/power/wake_lock 或wake_unlock 只是显示User Space 申请的wake lock, kernel 申请的wake lock显示不出来6. cat proc/wakelocks 可以显示所有的wake lock的信息7. Early suspend/Late resume中有一个关键wake lock是main_wake_lock, 执行early suspend后会unlock main_wake_lock;执行late resume之前会lock main_wake_lock.8. 当任何一个wake lock被unlock时,会检测是否有其他wake lock处于locked状态?如果没有则系统进入linux 常规suspend9. 一般而言android系统是否休眠,是由user space发起的,而kernel space 是不能主动进入休眠的;当android系统需要进入休眠时,user space 执行echo mem > sys/power/state;强迫kernel 进入early suspend状态,如果还没有任何wake lock被locked,则进入linux 常规suspend.10. 如果android系统没有进入深度休眠,则user space发起echo on> sys/power/state, 则系统马上执行late resume, 唤醒LCD,TS,sensor等;如果已经进入深度休眠,则另外处理11. kernel会依次同步文件系统,执行各设备注册的suspend, 执行system core 的suspend disble bus和irq等,然后进入深度休眠后会在suspend_enter@kernel/kernel/power/suspend.c中的 suspend_ops->enter(state) 系统挂起,直到有硬件的操作唤醒;一旦被唤醒则依次执行system core resume, device resume 等,最后还会执行late resume.12. User space 向kernel申请wake lock时, 写入sys/power/wake_lock 的buf格式为<wakelock名称> [延时的纳秒数];但是User space 没有这么使用,android在java层自己实现了计数wake lock和记次wake lock.13. Early suspend/late resume 针对LCD,TS等设备来说,所起的作用与suspend/resume是一样的。
【Android休眠】之Android休眠机制
【Android休眠】之Android休眠机制一、休眠概述休眠,简而言之就是设备在不需要工作的时候把一些部件、外设关掉(掉电或让它进入低功耗模式)。
为什么要休眠呢?一言以蔽之:省电。
休眠分主动休眠和被动休眠。
主动休眠:比如我电脑不用了,就通过设置让系统进入休眠模式;被动休眠:系统检测到自己闲的慌,为了节约故,自己就休眠去了。
废话不叙。
二、Android休眠休眠是内核的核心工作,而Android是基于Linux内核的,所以Android休眠和内核有着千丝万缕的联系;由于Android的特殊应用场景:移动设备,所以Android休眠和内核又有着特别的需求。
1、联系:Android设备停止使用,系统没有什么事情可做,进入休眠状态的功能最终是由内核去实现的;每一类硬件都有自己的驱动,具体的驱动决定怎么进入休眠以及处于何种层次的休眠。
比如:对于platform_device,就按照platform_driver定义的规则,在suspend 调用的时候,去做上面提到的事情:struct platform_driver {int (*probe)(struct platform_device *);int (*remove)(struct platform_device *);void (*shutdown)(struct platform_device *);int (*suspend)(struct platform_device *, pm_message_t state);int (*resume)(struct platform_device *);struct device_driver driver;const struct platform_device_id *id_table;};2、Android的特别需求:比如对于自己的电脑,不用让它休眠好了;但是对于我们形影不离的手机,在休眠的时候还要睁一只眼:来电了要通知你,QQ啊微信啊什么的由信息了也要通知你,所以Android在Linux内核休眠机制之上,提出了“Opportunistic Suspend”。
Android休眠流程总结
Android休眠流程总结1. framework层1.1 java层休眠流程中上层有很多种,⽐如按power key进⼊休眠流程,还是就是settings下⾯的⾃动息屏流程。
1.1.1 power key休眠流程当⽤户按下power key的时候,PhoneWindowManager类下的interceptBeforeQueueing, 在handle special key流程中,会命中KeyEvent.KEYCODE_POWER.其业务逻辑⾥⾯就会调⽤到inteceptPowerKeyDown和interceptPowerKeyUp, ⽽休眠流程的起始条件,灭屏流程就是从这个interceptPowerKeyUp开始的。
之后会就interceptPowerKeyUp展开,但我们先来看下从key event发出后,怎么⾛到interceptBeforeQueueing的,这⾥主要看下framework层的获得key event事件后响应流程,⾄于key event事件怎么分发的和怎么获得的需要InuptDispatcher(inputFlinger)部分来分析,之后有时间再补充。
com_android_server_input_InputManagerService.cpp在收到InputDispatcher分发的出来PowerKey 事件之后,就会⾛到NativeInputManager::dispatchUnhandledKey⽅法,这⾥⽅法⾥通过回调的机制回调到InputManagerService.java下⾯的native⽅法dispatchUnhandleKey,注意这个⽅法是回调⽅法。
然后在调到InputManagerCallback下⾯的dispatchUnhandleKey,然后再调到PhoneWindowManager下⾯的dispatchUnhandleKey⽅法,然后调到interceptFallback⽅法,最终从这⾥⾯调到interceptBeforeQueueing这个⽅法。
唤醒休眠的Android设备并做适当UI提醒的总结与思考
唤醒休眠的Android设备并做适当UI提醒的总结与思考最近在做的一个Android APP项目,需要实现这样的效果:当Android设备处于任何界面时(该APP正在后台运行),当有消息来到时,需要立刻弹出一个对话框提示;而如果设备是休眠状态时,需要立刻唤醒设备,提示对话框。
这有点类似于Android手机上的qq消息提示。
主要的难点是:如何唤醒设备,如何让对话框显示出来。
对于唤醒设备,很明显,是需要权限的。
在Androidmanifest.xml添加了相应的权限,貌似没有作用。
后台在贴吧上找到了一个说法,在oncreate函数中添加了下面的代码:final android.view.Window win = getWindow();win.addFlags(youtParams.FLAG_SHOW_ WHEN_LOCKED|youtParams.FLAG_DISMISS_KEYGUARD | youtParams.FLAG_KEEP_SCREEN_ON | youtParams.FLAG_TURN_SCREEN_ON);通过命名就可以知道,这部分获取到窗口的一个实例并添加了相应的标志位,就可以实现休眠唤醒。
对于这个部分,没有太多可以说的,也不再深究。
而对于第二个问题,确实费了一番功夫。
首先,对话框可以用一个activity来实现,改变其大小为合适大小。
但是此时,你会发现背景色还是有的,当然希望将背景色改为透明。
但是这还不是大问题,大问题是当有多条信息来到时,会有多个这样的对话框来到,用户需要多次点击屏幕才能清理这些对话框。
这样的效果肯定是不能接收的。
而且,如果在接收多条信息之前设备在别的应用或在桌面时,看不到这个对话框,只有进入该应用才可以看到。
网上有人提到了affinity属性,也有人提到使用“singleTask”启动这个activity。
试了一下,可以,但是当有多条信息到来时,仍然有问题,它始终显示的是第一条信息的内容,这也很容易让用户认为是个错误。
Android待机流程分析
Android待机流程分析Android待机流程分析以下分析基于android2.2的google源码。
开机启动时,首先执行PhoneWindowManager.systemReady()(这之前的流程不分析)。
调用KeyguardViewMediator.onSystemReady()进行待机锁屏及解锁逻辑。
KeyguardViewMediator是整个待机解/锁屏业务的调度器,负责调度锁屏界面的相关动作及查询解锁屏状态,包括以下一些内容:查询锁屏状态,及当前处于锁屏状态还是已解锁状态,PhoneWindowManager持有KeyguardViewMediator的引用,当用户触摸屏幕或者按下某个键是,PhoneWindowManager会通过KeyguardViewMediator查询锁屏状态(锁定/解锁),进行不同的响应处理。
如果处于锁定状态,系统输入事件会受到限制。
响应电源事件(黑/亮屏)。
判断锁屏界面应该处于什么状态(显示或者重置)。
手机黑屏后,锁屏界面马上就会显示出来,以便下一次亮屏后,马上就能显示锁屏界面,而不会出现闪烁或延时。
其他应用程序或者服务也可以请求禁止锁屏(通过调用KeyguardViewMediator的setKeyguardEnabled(boolean)方法)。
例如接听来电界面。
KeyguardViewMediator类在WindowManagerPolicy(在手机系统中是PhoneWindowManager实例)初始化时被创建,并运行在它的线程上,锁屏的UI界面也是在这个线程上创建及显示的。
KeyguardViewMediator类提供的状态查询api可以被诸如android.view.WindowManager、com.android.server.InputManager等其它线程调用,所以,KeyguardViewMediator类上的这些api方法都是线程同步的(synchronized)。
- 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状态。