待機異常篇

來源:互聯網
上載者:User

標籤:android待機

待機異常篇

待機異常篇待機異常
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有幾次進入待機狀態。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

待機異常篇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.