Understanding Android Alarm: Architecture, Types, and Power‑Saving Strategies
This article explains Android's Alarm mechanism, covering its overall architecture, the four alarm types, framework and kernel workflows, batch alignment, wake‑up handling, suspend processing, and a real‑world power‑debugging case to help developers optimize battery consumption.
Background
Alarm is used for scheduling tasks in Android and appears across many system layers. Unlike timer, an alarm can wake a device from suspend, which makes it essential for power‑management debugging when frequent wake‑ups increase consumption.
Overall Architecture
The framework layer exposes APIs and implements policies (creation, processing, alignment). It communicates with native code via JNI, and the native layer invokes kernel system calls. Different alarm types are distinguished by parameters in the framework and handled in the kernel, especially regarding wake‑up behavior.
Alarm Types
Four alarm categories are defined based on wake‑up capability and time reference:
RTC_WAKEUP : UTC wall‑clock time, wakes the device.
RTC : UTC wall‑clock time, does not wake the device.
ELAPSED_REALTIME_WAKEUP : Time since boot, wakes the device.
ELAPSED_REALTIME : Time since boot, does not wake the device.
Detailed explanations are available in the source code comments.
Alarm Framework Flow
Key Interfaces
AlarmManager provides the following public methods:
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)Main Process
Initialization – create epoll listeners for alarm states.
Alarm setting – after validation and alignment, the alarm is passed to setAlarm() in the native layer.
Alarm handling – when an alarm fires, AlarmThread processes it in a loop, possibly handling multiple alarms from the same batch.
Alarm Alignment (Batching)
Non‑exact alarms are grouped into batches based on their trigger time and maximum trigger window, reducing wake‑ups. Exact alarms get their own batch to preserve timing precision.
Batch initialization : If an alarm cannot fit an existing batch, a new batch is created with mStart and mEnd set to the alarm's trigger and maximum times.
Trigger time calculation : mWhenElapsed = max(minTrigger, nominalTrigger) – minTrigger is the elapsed time since boot; for app‑level alarms an extra 5 seconds is added. mMaxWhenElapsed = mWhenElapsed + windowLength. For exact alarms windowLength = 0, so the two values are equal.
Batch admission criteria :
Alarm is non‑exact. mWhenElapsed ≤ batch.mEnd and mMaxWhenElapsed ≥ batch.mStart.
When an alarm joins a batch, the batch’s time boundaries are dynamically shrunk to reflect the new alarm’s limits.
Kernel Flow
System Calls
SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags); // initialize SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr); // set alarm SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr); // get alarm timeAlarm Setting Path
The framework’s setAlarm() ultimately calls timerfd_settime(), which reaches the kernel.
Wake‑up vs. Non‑wake‑up Handling
Framework alarm types ending with _WAKEUP map to kernel clock IDs ending with _ALARM. Wake‑up alarms use hrtimer plus an extra enqueue step ( alarmtimer_enqueue()) so that during suspend the alarm is moved to the RTC and can wake the device.
Suspend Processing
During alarmtimer_suspend():
The nearest alarm is taken from the timer queue and programmed into the RTC to enable wake‑up.
If the next alarm is within 2 seconds, the system stays awake for an additional 2 seconds to avoid rapid suspend‑wake cycles.
Alarm Trigger
AlarmThreadcontinuously waits for alarm events. Whether triggered by an hrtimer or an RTC interrupt, the final step calls timerfd_triggered(), which notifies the framework via epoll.
Debugging Case Study
During power‑consumption debugging, frequent alarm wake‑ups were observed:
Standby current measured ~65 mA with many spikes.
Kernel logs showed repeated alarm wake‑ups (e.g., gic_show_resume_irq, spmi_show_resume_irq). dumpsys alarm revealed Google Play Services ( com.google.android.gms) generating many wake‑up alarms.
Removing the GMS package reduced standby current to ~8 mA, confirming the impact of excessive alarms.
Conclusion
The article covered Android alarm’s overall workflow, API usage, batch alignment, kernel interactions, wake‑up handling, and a practical debugging example, providing a useful reference for developers seeking to understand or optimise alarm‑related power consumption.
References
https://blog.csdn.net/weixin_50019298/article/details/121307485 – “Android中Alarm的机制”
https://www.jianshu.com/p/e81fac39023b – “Android电源管理‑AlarmManager”
OPPO Kernel Craftsman
Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
