Android Linux Alarm 對功耗的影響

1、 Alarm介紹

1.1 alarm的幾種類型及區別

在這裏插入圖片描述

  • 可喚醒:RTC_WAKEUP、ELAPSED_REALTIME_WAKEUP、RTC_POWEROFF_WAKEUP
  • 不可喚醒:RTC、ELAPSED_REALTIME
  • 使用相對時間:ELAPSED_REALTIME_WAKEUP、ELAPSED_REALTIME
  • 使用絕對時間:RTC_WAKEUP、RTCRTC_POWEROFF_WAKEUP

1.2 alarm相關接口

Frameworks\base\core\java\android\app\AlarmManager.java
設置一次性鬧鐘:

public void set(int type, long triggerAtMillis, PendingIntent operation)

設置重複鬧鐘:

public void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)

設置精確鬧鐘:

public void setExact(int type, long triggerAtMillis, PendingIntent operation)

1.3 batch——減少設備喚醒次數以節省功耗

在這裏插入圖片描述

2、alarm關鍵流程

2.1 Alarm關鍵流程分析——init

在這裏插入圖片描述

2.2 Alarm關鍵流程分析——set

在這裏插入圖片描述

2.3 Alarm關鍵流程分析——trigger

在這裏插入圖片描述

3、dumpsys alarm解析

1、Batches

Batch{2159934 num=1 start=68436475 end=69786475 flgs=0x8}:
    ELAPSED #0: Alarm{a18435d type 3 when 68436475 android}
      tag=*alarm*:com.android.server.action.NETWORK_STATS_POLL
      type=3 whenElapsed=+1m1s648ms when=+1m1s648ms
      window=+22m30s0ms repeatInterval=1800000 count=0 flags=0x8
      operation=PendingIntent{7c934d2: PendingIntentRecord{b2fa9a3 android broadcastIntent}}

2、Top Alarms

This is the top ten alarms ranked in descending order by total aggregate time that the alarm code has run.
example:

  Top Alarms:
    +19s42ms running, 0 wakeups, 131 alarms: 1000:android
         *alarm*:android.intent.action.TIME_TICK
    +12s846ms running, 3 wakeups, 3 alarms: u0a1:com.android.providers.calendar                    
        *walarm*:com.android.providers.calendar.intent.CalendarProvider2
    +3s148ms running, 0 wakeups, 36 alarms: 1000:android
        *alarm*:com.android.server.action.NETWORK_STATS_POLL
     ...		

3、Alarm Stats

This section shows stats for all of the alarms that have run since the system was last restarted.
example:

  u0a1:com.android.providers.calendar +12s846ms running, 3 wakeups:
       +12s846ms 3 wakes 3 alarms, last -14h49m11s138ms:
           *walarm*:com.android.providers.calendar.intent.CalendarProvider2
  u0a20:com.android.systemui +7ms running, 1 wakeups:
      +7ms 1 wakes 1 alarms, last -17h14m13s266ms:                                            *walarm*:com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD
 ...

4、Case實例分析

Case實例分析一

Case# 03370456 High power consumption in LTE mode in 1hr test after factory reset
在這裏插入圖片描述

kernel log - - echo 1 > /sys/module/msm_show_resume_irq/parameters/debug_mask

串口 log / dmesg 輸出

[  596.785361] PM: suspend entry 2018-03-05 12:29:05.258977443 UTC
[  597.212284] gic_show_resume_irq: 302 triggered 7781b8.qcom,mpm
[  597.212284] gic_show_resume_irq: 170 triggered null
[  597.212284] PM: Calling msm_pinctrl_resume+0x0/0x190
[  597.212284] PM: Calling spmi_pmic_arb_resume+0x0/0x34
[  597.212284] spmi_show_resume_irq: 403 triggered [0x0, 0x61, 0x1] **qpnp_rtc_alarm**
[  597.455898] PM: suspend exit 2018-03-05 12:29:18.156313167 UTC

dumpsys alarm log

  Alarm Stats:
  u0a21:com.google.android.gms +1m7s937ms running, 432 wakeups:
    +36s855ms 37 wakes 37 alarms, last -3m22s840ms:
      *walarm*:com.google.android.intent.action.GCM_RECONNECT
      ...

去掉GMS包及第三方應用後
在這裏插入圖片描述

Case實例分析二

case#03495555 How to optimize the Current Consumption

休眠底電流正常;
休眠時間短;
電流有頻繁的peak.

打開Alarm 喚醒中斷輸出功能

echo 1 > /sys/module/msm_show_resume_irq/parameters/debug_mask

串口 log / dmesg 輸出

[  257.256947] __qpnpint_handle_irq: 294 triggered [0x0, 0x61,0x1] qpnp_rtc_alarm
[  257.256947] gic_show_resume_irq: 200 triggered qcom,smd-rpm
[  257.256947] gic_show_resume_irq: 203 triggered 601d0.qcom,mpm
[  257.256947] gic_show_resume_irq: 222 triggered 200f000.qcom,spmi
[  257.507936] PM: suspend exit 2018-05-30 07:16:58.144607378 UTC

打開AlarmManagerService Debug Code

class AlarmManagerService extends SystemService {
...
- static final boolean localLOGV = false;
+ static final boolean localLOGV = true;
...
}

2303 if (localLOGV) {
2304 for (int i=0; i<triggerList.size(); i++) {
2305 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2306 }
2307 }

logcat 輸出

05-30 15:16:58.132  1835  2931 V AlarmManager: Triggering alarm #0: Alarm{104a96b type 0 when 1527664617148 com.MobileTornado.Main}
05-30 15:16:58.134  1835  2931 V AlarmManager: sending alarm Alarm{104a96b type 0 when 1527664617148 com.MobileTornado.Main}

05-30 15:09:52.644  1835  2931 V AlarmManager: Triggering alarm #0: Alarm{328145 type 0 when 1527664192636 com.MobileTornado.Main}
05-30 15:09:52.768  1835  2931 V AlarmManager: Triggering alarm #0: Alarm{fe048f2 type 0 when 1527664192764 com.MobileTornado.Main}
05-30 15:09:53.668  1835  2931 V AlarmManager: Triggering alarm #0: Alarm{2cf766d type 0 when 1527664193662 com.MobileTornado.Main}

優化措施:

移除com.MobileTornado.Main測試驗證;
應用修改,減小設置alarm頻率。

Case實例分析三

print alarm log:

Add below code in /kernel/drivers/rtc/interface.c

int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
	int err;
	err = rtc_valid_tm(&alarm->time);
	if (err != 0)
	return err;
	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;
		if (rtc->aie_timer.enabled) {
		rtc_timer_remove(rtc, &rtc->aie_timer);
	}
	rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
	rtc->aie_timer.period = ktime_set(0, 0);
	if (alarm->enabled) {
++ 		dump_stack();
++ 		printk("rtc_set_alarm printk: %llu",rtc->aie_timer.node.expires);
		err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
	}
	mutex_unlock(&rtc->ops_lock);
	return err;
}
  1. /kernel/kernel/time/alarmtimer.c
int alarm_start(struct alarm *alarm, ktime_t start)
{
	struct alarm_base *base = &alarm_bases[alarm->type];
	unsigned long flags;
	int ret;
	
	spin_lock_irqsave(&base->lock, flags);
	alarm->node.expires = start;
++ 	dump_stack();
++ 	printk("alarm_start: set %llu",ktime_to_ms(alarm->node.expires));
	alarmtimer_enqueue(base, alarm);
++ 	printk("alarm_start: set real %llu",ktime_to_ms(alarm->node.expires));
	ret = hrtimer_start(&alarm->timer, alarm->node.expires,
	HRTIMER_MODE_ABS);
	spin_unlock_irqrestore(&base->lock, flags);
	
	return ret;
}

You can also enable AlarmManagerService logs, by default the alarm log level is Verbose(not printed) in android, for example,

/frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
->triggerAlarmsLocked

class AlarmManagerService extends SystemService {
...
- static final boolean localLOGV = false;
+ static final boolean localLOGV = true;
...
}

2303 if (localLOGV) {
2304 for (int i=0; i<triggerList.size(); i++) {
2305 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2306 }
2307 }

Wu_Being博客聲明:本人博客歡迎轉載,請標明博客原文和原鏈接!謝謝!
《Android Linux Alarm 對功耗的影響》:
https://wu-being.blog.csdn.net/article/details/88390231

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章