待机异常篇

待机异常篇

待机异常篇待机异常

1: 按Power key后,连early_suspend都没进。待机异常

2: 可以进early_suspend,但进不了suspend待机异常

3: 可以进suspend,但出现:PM: Some devices failed to suspend待机异常

4: 可以进入到suspend_enter,suspend流程走完了,但很快被唤醒待机异常

5: 可以进入到suspend_enter,也不被唤醒,但电流很大,CPU也较烫

关于early_suspend:

由于/sys/power/autosleep在处理suspend时,并没有像/sys/power/state那样,有对earlysuspend的兼容处理,如:

Kernel/kernel/power/main.c

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
               const char *buf, size_t n)
{
....
#ifdef CONFIG_EARLYSUSPEND
        if (state == PM_SUSPEND_ON || valid_state(state)) {
            error = 0;
            request_suspend_state(state);
        }
#else
        error = pm_suspend(state);
#endif

进入request_suspend_state会先处理earlysuspend,然后再进入suspend。

而autosleep在处理时,是直接进入pm_suspend,不会去处理earlysuspend。

因此,不同平台处理earlysuspend的方式也不同,如Intel平台是通过将所有/sys/power/early_suspend/xxdevic/early_suspend文件写1使其对应的设备进入earlysuspend(代码路径:hardware\libhardware\modules\power\),该操作发生在上图ANDROID待机流程的blankAllDisplays,在blankAllDisplays函数里,会先调用nativeSetInteractive进入early_suspend,再调用nativeSetAutoSuspend进入suspend。

/sys/power/early_suspend/xxdevic/early_suspend 节点通过下面接口生成:

device_create_file(&dev->pdev->dev, &dev_attr_early_suspend);

register_early_suspend_device(&dev->pdev->dev);

待机异常1 :按Power key后,连early_suspend都没进。

问题分析

这种情况发生在Android待机流程中的goToSleepInternal,由于不满足待机条件而无法进入待机。

不能进入待机的条件:

private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {

        if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
                || !mBootCompleted || !mSystemReady) {
            return false;
        }

事件时间和电源状态一般不会是异常的因素,因此引起异常的主要是mBootCompleted 和mSystemReady 两个条件。

调试方法

mBootCompleted在收到Intent.ACTION_BOOT_COMPLETED广播后置1,而Intent.ACTION_BOOT_COMPLETED广播是在进入到Launcher后发出的,frameworks\base\services\java\com\android\server\am\ActivityManagerService.java,因此当系统启动异常时进入不到Launcher,就无法待机;还有一种情问,多Launcher选择界面时也因没进入Launcher而不发ACTION_BOOT_COMPLETED广播而造成待不了机。

当ActivityManagerService跑起来就表示mSystemReady 为true,可以通过查看logcat,如果看到有“Activity Manager”的log表示已跑ActivityManagerService,如果看到“** Failure starting bootstrap service”,表示启动失败。

待机异常2:可以进early_suspend,但进不了suspend

问题分析

进入suspend时,会调用pm_get_wakeup_count,如果系统存在wake_lock就会卡在这个函数里,如:

pm_get_wakeup_count:

prepare_to_wait(&wakeup_count_wait_queue, &wait,

TASK_INTERRUPTIBLE);

当wake_lock释放完毕时才会唤醒该wait,如下inpr = 0:

wakeup_source_deactivate:

if (!inpr && waitqueue_active(&wakeup_count_wait_queue))

wake_up(&wakeup_count_wait_queue);

调试方法

在串口终端下,不要连接USB,连USB会产生wake_lock,cat /sys/power/wakeup_count,这时会去调用pm_get_wakeup_count,如果cat也卡住,说明存在suspend确实是卡在wake_lock上。

Wake_lock有些是android进程加的和有些是kernel进程加的。可以通过命令cat /sys/kernel/debug/wakeup_sources 来查看所有的wake_lock,如下:

active_since 所在列,如果有数值大于0,表示其所对应的行是当前活动的wake_lock,如上图,PowerManagerService.WakeLocks和dwc_wake_lock是活动的。

原代码的打印有可能对不齐,下面的改动可以让其对齐:

--- a/kernel/drivers/base/power/wakeup.c
+++ b/kernel/drivers/base/power/wakeup.c
@@ -842,8 +842,7 @@ static int print_wakeup_source_stats(struct seq_file *m,

-       ret = seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t"
-                       "%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
+       ret = seq_printf(m, "%-35s%-15lu%-15lu%-15lu%-15lu%-15lld%-15lld%-15lld%-15lld%-15lld\n",
                        ws->name, active_count, ws->event_count,
                        ws->wakeup_count, ws->expire_count,
                        ktime_to_ms(active_time), ktime_to_ms(total_time),
@@ -863,9 +862,8 @@ static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
 {

-       seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
-               "expire_count\tactive_since\ttotal_time\tmax_time\t"
-               "last_change\tprevent_suspend_time\n");
+       seq_printf(m, "%-35s%-15s%-15s%-15s%-15s%-15s%-15s%-15s%-15s%-15s\n",
+                       "name","active_count","event_count","wakeup_count","expire_count","active_since","total_time","max_time","last_chang

android加的wake_lock可以通过命令cat /sys/power/wake_lock来查看,再在kernel/kernel/power/main.c 的wake_lock_store函数里加上打印: printk(“pid %d wirte %s to /sys/power/wake_lock\n”,current->pid,buf);,将pid打印出来,然后cat /proc/进程ID/status 来查看具体进程(也可以 ps 进程ID号来查看)。

待机异常3: 可以进suspend,但出现:PM: Some devices failed to suspend

问题分析

有些设备在待机时失败了。

调试方法

首先用命令cat /sys/kernel/debug/suspend_stats查看待机异常发生在哪个阶段,如下:

success: 3

fail: 1

failed_freeze: 0

failed_prepare: 0

failed_suspend: 1

failed_suspend_late: 0

failed_suspend_noirq: 0

failed_resume: 0

failed_resume_early: 0

failed_resume_noirq: 0

failures:

last_failed_dev:

last_failed_errno: -16

0

last_failed_step: suspend

failed_suspend 的记数大于0表示在device_suspend阶段异常。

从log可以看到,如果是这样的字段:

active wakeup source: event3-556

PM: Some devices failed to suspend

则表示有些活动wakeup锁还没释放。在kernel/drivers/base/power/wakeup.c的wakeup_source_add函数里添加打印:

printk(“%s:%s\n”,FUNCTION,ws->name);

dump_stack();

跟踪出哪个驱动,然后在该驱动里跟踪wakeup锁。

如果log是这样的:

PM: Device xxx failed to xxx: error x

PM: Some devices failed to suspend

则表示有设备在待机时失败,根据设备名找到相应驱动,然后跟踪该驱动suspend失败的原因。

另外,将kernel/kernle/printk.c里的ignore_loglevel置1:

Kernel/kernel/printk.c

static bool __read_mostly ignore_loglevel=1;

用命令echo 1 > /sys/power/pm_print_times 打开kernel/drivers/base/power/main.c里的initcall_debug_report打印,这样,在待机时就可以打印出哪些设备待机成功或失败。

待机异常4: 可以进入到suspend_enter,suspend流程走完了,但很快被唤醒

问题分析

Suspend流程走完后被唤醒,说明有唤醒源异常,造成异常唤醒。

调试方法

首先用命令cat /sys/kernel/debug/suspend_stats查看待机过程是否正常,如果正常,那么需要找出唤醒源。

打开kernel/kernel/irq/pm.c的resume_irqs函数里的打印信息:

#ifdef CONFIG_PM_DEBUG
        if (desc->istate & IRQS_PENDING) {
            printk(KERN_DEBUG "Wakeup from IRQ %d %s\n",
                irq,
                desc->action && desc->action->name ?
                desc->action->name : "");
        }
#endif /* CONFIG_PM_DEBUG */

从打印信息里可以看出是哪个中断号唤醒的,命令cat /proc/interrupts可以查看所有中断。另外,在kernel/kernel/irq/manage.c 的__setup_irq函数里加打印及dump_stack,跟踪哪个驱动注册了该irq号:

printk("%s:irq = %d,name = %s\n",__FUNCTION__,irq,new->name ?
            new->name : "");
dump_stack();

待机异常5: 可以进入到suspend_enter,也不被唤醒,但电流很大,CPU也较烫

问题分析

进入suspend_enter且不被唤醒,说明系统已进入待机,应该是SOC没进入待机状态造成

调试方法

可以在suspend_enter加SOC power state的寄存器的打印,或者跟vendor要soc待机的调试手段,比如 intel平台,可以通过查询cat /sys/kernel/debug/mid_pmu_states 查询cpu有几次进入待机状态。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 03:18:02

待机异常篇的相关文章

hive 学习之异常篇

一.刚装上hive在执行hive启动的过程中出现 [[email protected] hive-0.6.0]$ hive Invalid maximum heap size: -Xmx4096m The specified size exceeds the maximum representable size. Could not create the Java virtual machine. 解决方法: 修改$HIVE_INSTALL/bin/ext/util/execHiveCmd.sh

java中级异常篇

一.异常 1.异常的概述 什么是异常:是程序运行过程中发生未知的事件,  该事件可以中断程序指令的正常执行流程. java中异常类的视图: 说明:Error和Exception的子类可以分为上图中的几类,并非所有子类. Throwable: Throwable 类是 Java 语言中所有错误或异常的超类.只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 throw语句抛出. Error: Error 是 Throwable 的子类,用于指示合理的应用程序不应该试图捕获的严

(转)ElasticSearch教程——汇总篇

https://blog.csdn.net/gwd1154978352/article/details/82781731 环境搭建篇 ElasticSearch教程——安装 ElasticSearch教程——安装Head插件 ElasticSearch教程——安装IK分词器插件 ElasticSearch教程——安装Kibana 基础操作 ElasticSearch教程——Kibana简单操作ES ElasticSearch教程——批量处理(mget和bulk) ElasticSearch教程—

toArray方法-转载

toArray方法可能报空指针异常和类型转换异常 篇一: ArrayList提供了一个将List转为数组的一个非常方便的方法toArray.toArray有两个重载的方法: 1.list.toArray(); 2.list.toArray(T[]  a); 对于第一个重载方法,是将list直接转为Object[] 数组: 第二种方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型. 不明真像的同学喜欢用第一个,是这样写: 1 2 3 4 5 6 7 Arra

Java求职基础知识

从当初的电面,到后来的串讲,再到后来的技术面,一路走来,感触颇深,今天把这些东西晒出来,希望能给正在和准备找工作的同学们提供一些参考. 在进入正题之前,插播一段废话,没有良好的Java基础的同学怎么办,take it easy,从你看到这篇日志开始,全心全力用三周的时间,找一本页数在250页以内的Java教材(超过250页的书除非你是250,否则很难在三周内搞定),认认真真的看,老老实实的练. 接下来要说的是常见面试题,前提是要有Java基础,否则看了也没用,没有Java基础,是不会有面试的机会

wakelock查看

Android的wakelock分为两层 待机异常https://wenku.baidu.com/view/6b765c8802020740be1e9bd8.html Linux层和应用层 查看Linux的wakelock 在adb shell中使用命令#cat /sys/power/wake_lock (1)内核没有加锁时,如下图显示 (2)当内核有进程加锁时,例如我对屏幕进行解锁 查看应用程序的wakelock,学习对dumpsys中各种log进行分析 在adb shell中使用# dump

诗经 全文

诗经 全文 (带注释和译文) http://www.edu009.com/Article/HTML/Article_60756.html <诗经> 春秋·孔丘 <诗经>是我国第一部诗歌总集,先秦时代称为“诗”或“诗三百”,孔子加以了整理.汉武帝采纳董仲舒“罢黜百家,独尊儒术”的建议,尊“诗”为经典,定名为<诗经>. <诗经>现存诗歌 305 篇,包括西周初年到春秋中叶共 500 余年的民歌和朝庙乐章,分为风.雅.颂三章. “风”包括周南.召南.邶.鄘.卫.王

python——面向对象篇之异常和反射

内置函数isinstance和issubclass 1.1 isinstance用法: 1 isinstance(string,str) 判断第一个参数是否是第二个参数的子集,例如: 1 print isinstance("test",str) #判断test是否是字符串类型 2 3 C:\Python27\python.exe D:/python/s11/8day/反射/test.py 4 5 True 6 7 8 print isinstance(123,int) #判断123是否

【Python五篇慢慢弹(4)】模块异常谈python

模块异常谈python 作者:白宁超 2016年10月10日12:08:31 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc入门资料包含了基本要点.本文是对文档常用核心要点进行梳理,简单冗余知识不再介绍,作者假使你用c/java/c#/c++任一种语言基础.本系列文章属于入门内容,老鸟可以略看也可以略过,新鸟可以从篇一<快速上手学python>先接触下python怎样安装与运行,以及pycharm编辑器的使用和配置: