赞
踩
Android的aralm可以唤醒系统,先看ararm调用过程
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/AlarmManager.java
- public void set(@AlarmType int type, long triggerAtMillis, PendingIntent operation) {
- setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null,
- null, null, null);
- }
- private void setImpl(@AlarmType int type, long triggerAtMillis, long windowMillis,long intervalMillis, int flags, PendingIntent operation, final OnAlarmListener listener,String listenerTag, Handler targetHandler, WorkSource workSource,AlarmClockInfo alarmClock) {
- mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,
- operation, recipientWrapper, listenerTag, workSource, alarmClock);
- }
- private final IBinder mService = new IAlarmManager.Stub() {
- @Override
- public void set(String callingPackage,
- int type, long triggerAtTime, long windowLength, long interval, int flags,
- PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
- WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
- setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
- listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
- }
- }
- void setImpl(int type, long triggerAtTime, long windowLength, long interval,
- PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
- int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
- int callingUid, String callingPackage) {
-
- setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
- interval, operation, directReceiver, listenerTag, flags, true, workSource,
- alarmClock, callingUid, callingPackage);
- }
- private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
- long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
- String listenerTag, int flags, boolean doValidate, WorkSource workSource,
- AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
- Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
- operation, directReceiver, listenerTag, workSource, flags, alarmClock,
- callingUid, callingPackage);
- setImplLocked(a, false, doValidate);
- }
- private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
- rescheduleKernelAlarmsLocked();
- }
- void rescheduleKernelAlarmsLocked() {
- setLocked(ELAPSED_REALTIME, nextNonWakeup);
- }
- private void setLocked(int type, long when) {
- final int result = set(mNativeData, type, alarmSeconds, alarmNanoseconds);
- }
private native int set(long nativeData, int type, long seconds, long nanoseconds);
- static const JNINativeMethod sMethods[] = {
- {"set", "(JIJJ)I", (void*)android_server_AlarmManagerService_set},
- }
-
- static jint android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
- {
- const int result = impl->set(type, &ts);
- }
-
- int AlarmImpl::set(int type, struct timespec *ts)
- {
- return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
- }
通过系统调用设置内核时间
- SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
- const struct itimerspec __user *, utmr,
- struct itimerspec __user *, otmr)
- {
- struct itimerspec new, old;
- int ret;
-
- if (copy_from_user(&new, utmr, sizeof(new)))
- return -EFAULT;
- ret = do_timerfd_settime(ufd, flags, &new, &old);
- if (ret)
- return ret;
- if (otmr && copy_to_user(otmr, &old, sizeof(old)))
- return -EFAULT;
-
- return ret;
- }
找最近的一个唤醒闹钟,设置到rtc里,时间到了,rtc产生中断唤醒cpu
- static const struct dev_pm_ops alarmtimer_pm_ops = {
- .suspend = alarmtimer_suspend,
- };
-
- static struct platform_driver alarmtimer_driver = {
- .driver = {
- .name = "alarmtimer",
- .pm = &alarmtimer_pm_ops,
- },
- .shutdown = alarmtimer_shutdown,
- };
-
- static int alarmtimer_suspend(struct device *dev)
- {
- struct rtc_time tm, tm_set;
- ktime_t min, now, set_time;
- unsigned long flags;
- struct rtc_device *rtc;
- struct rtc_wkalrm alarm;
- int i, ret = 0;
-
- spin_lock_irqsave(&freezer_delta_lock, flags);
- min = freezer_delta;
- freezer_delta = ktime_set(0, 0);
- spin_unlock_irqrestore(&freezer_delta_lock, flags);
-
- rtc = alarmtimer_get_rtcdev();
- /* If we have no rtcdev, just return */
- if (!rtc)
- return 0;
-
- /* Find the soonest timer to expire*/
- for (i = 0; i < ALARM_NUMTYPE; i++) {
- struct alarm_base *base = &alarm_bases[i];
- struct timerqueue_node *next;
- ktime_t delta;
-
- spin_lock_irqsave(&base->lock, flags);
- next = timerqueue_getnext(&base->timerqueue);
- spin_unlock_irqrestore(&base->lock, flags);
- if (!next)
- continue;
- delta = ktime_sub(next->expires, base->gettime());
- if (!min.tv64 || (delta.tv64 < min.tv64))
- min = delta;
- }
- if (min.tv64 == 0)
- return 0;
-
- if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
- __pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
- return -EBUSY;
- }
-
- /* Setup an rtc timer to fire that far in the future */
- rtc_timer_cancel(rtc, &rtctimer);
- rtc_read_time(rtc, &tm);
-
- now = rtc_tm_to_ktime(tm);
- set_time = ktime_add(now, min);
- tm_set = rtc_ktime_to_tm(set_time);
- pr_info("Suspend alarm: %d-%d-%d %d:%d:%d\n", tm_set.tm_year + 1900,
- tm_set.tm_mon + 1, tm_set.tm_mday, tm_set.tm_hour,
- tm_set.tm_min, tm_set.tm_sec);
-
- alarm.time = tm_set;
- alarm.enabled = 1;
- if (rtc->ops && rtc->ops->set_alarm) {
- ret = rtc->ops->ioctl(rtc->dev.parent,
- SET_WAKE_ALARM, (unsigned long)&alarm);
- /* Set alarm, if in the past reject suspend briefly to handle */
- if (ret < 0) {
- pr_err("Suspend alarm setting error %d\n", ret);
- __pm_wakeup_event(ws, MSEC_PER_SEC);
- }
- }
-
- return ret;
- }
某次抓的log如下,也就是说ararm的唤醒都是可预期的(Suspend ararm是格林威治时间,转换成北京时间需+8)
- [09-24 17:35:00.017] <6>[ 53.283769] c0 Suspend alarm: 2019-9-24 9:35:0
- [09-24 17:35:06.009] <6>[ 55.383820] c0 Suspend alarm: 2019-9-24 9:35:6
- [09-24 17:35:12.010] <6>[ 57.593710] c0 Suspend alarm: 2019-9-24 9:35:12
- [09-24 17:39:03.010] <6>[ 59.693765] c0 Suspend alarm: 2019-9-24 9:39:3
- [09-24 17:45:00.024] <6>[ 61.804539] c0 Suspend alarm: 2019-9-24 9:45:0
- [09-24 18:00:00.024] <6>[ 64.024533] c0 Suspend alarm: 2019-9-24 10:0:0
- [09-24 18:15:00.023] <6>[ 66.244466] c0 Suspend alarm: 2019-9-24 10:15:0
- [09-24 18:30:00.024] <6>[ 68.364377] c0 Suspend alarm: 2019-9-24 10:30:0
- [09-24 18:33:47.025] <6>[ 70.584263] c0 Suspend alarm: 2019-9-24 10:45:0
- [09-24 18:33:57.023] <6>[ 72.104397] c0 Suspend alarm: 2019-9-24 10:45:0
- [09-24 18:38:08.025] <6>[ 72.724177] c0 Suspend alarm: 2019-9-24 10:45:0
-
-
- [09-24 17:35:00.041] <6>[ 53.298469] c0 RTC ***** interrupt happen
- [09-24 17:35:06.015] <6>[ 55.397274] c0 RTC ***** interrupt happen
- [09-24 17:35:12.015] <6>[ 57.607150] c0 RTC ***** interrupt happen
- [09-24 17:39:03.015] <6>[ 59.707245] c0 RTC ***** interrupt happen
- [09-24 17:45:00.068] <6>[ 61.827663] c0 RTC ***** interrupt happen
- [09-24 18:00:00.030] <6>[ 64.047574] c0 RTC ***** interrupt happen
- [09-24 18:15:00.030] <6>[ 66.267515] c0 RTC ***** interrupt happen
Android上层通过poll一直在监听ararm,接收到通知后,将相应的事件进行分发。只有type类型为0或者2的alarm客户唤醒系统。可以根据打印信息查找唤醒系统的闹钟,如
- 09-19 15:00:05.968 813 952 D AlarmManager: sending alarm.type = 2, action = com.android.providers.calendar.intent.CalendarProvider2, cn = ComponentInfo{com.android.providers.calendar/com.android.providers.calendar.CalendarProviderBroadcastReceiver}, operation = PendingIntent{3eaf5c8: PendingIntentRecord{29dc661 com.android.providers.calendar broadcastIntent}}
-
- 09-19 15:01:46.941 813 952 D AlarmManager: sending alarm.type = 0, action = null, cn = ComponentInfo{cn.showmac.vsimservice/cn.jpush.android.service.AlarmReceiver}, operation = PendingIntent{ec569d7: PendingIntentRecord{c33696d cn.showmac.vsimservice broadcastIntent}}
- public class AlarmManager {
- public static final int RTC_WAKEUP = 0;
- public static final int RTC = 1;
- public static final int ELAPSED_REALTIME_WAKEUP = 2;
- public static final int ELAPSED_REALTIME = 3;
- }
- private class AlarmThread extends Thread
- {
- public AlarmThread()
- {
- super("AlarmManager");
- }
-
- public void run()
- {
- ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
-
- while (true)
- {
- int result = waitForAlarm(mNativeData);
- deliverAlarmsLocked();
- }
- }
此外,休眠后,系统默认每10min(展讯的15min,看代码定义)唤醒一次系统,更新电池状态,也是通过定时器实现的,代码如下
http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/health/2.0/default/healthd_common.cpp
- static void wakealarm_init(void) {
- wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK);
- wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);
- }
-
- static int healthd_init() {
- wakealarm_init();
- }
设置成15分钟,从上面的唤醒时间9.45,10:00,10:15,10:30也跟代码的一致。
- // Periodic chores fast interval in seconds
- #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
- // Periodic chores fast interval in seconds
- #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
- void healthd_battery_update_internal(bool charger_online) {
- int new_wake_interval = charger_online ? healthd_config.periodic_chores_interval_fast
- : healthd_config.periodic_chores_interval_slow;
- if (new_wake_interval != wakealarm_wake_interval) wakealarm_set_interval(new_wake_interval);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。