Mobile Development 11 min read

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.

OPPO Kernel Craftsman
OPPO Kernel Craftsman
OPPO Kernel Craftsman
Understanding Android Alarm: Architecture, Types, and Power‑Saving Strategies

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 time

Alarm 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

AlarmThread

continuously 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”

Debuggingmobile developmentAndroidKernelpower managementAlarmManager
OPPO Kernel Craftsman
Written by

OPPO Kernel Craftsman

Sharing Linux kernel-related cutting-edge technology, technical articles, technical news, and curated tutorials

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.