文章目錄
1、 Alarm介紹
1.1 alarm的幾種類型及區別
- 可喚醒:RTC_WAKEUP、ELAPSED_REALTIME_WAKEUP、RTC_POWEROFF_WAKEUP
- 不可喚醒:RTC、ELAPSED_REALTIME
- 使用相對時間:ELAPSED_REALTIME_WAKEUP、ELAPSED_REALTIME
- 使用絕對時間:RTC_WAKEUP、RTC、RTC_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;
}
/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