private final AlarmThread mWaitThread = new AlarmThread();
public AlarmManagerService(Context context) {
...
if (mDescriptor != -1) {
mWaitThread.start();
} else {
Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
}
}
private class AlarmThread extends Thread
{
public AlarmThread()
{
super("AlarmManager");
}
public void run()
{
ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
while (true)
{
int result = waitForAlarm(mDescriptor);
...
}
}
}
/**
* Broadcast Action: The current time has changed. Sent every
* minute. You can <em>not</em> receive this through components declared
* in manifests, only by explicitly registering for it with
* {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
* Context.registerReceiver()}.
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
public AlarmManagerService(Context context) {
...
mTimeTickSender = PendingIntent.getBroadcastAsUser(context, 0,
new Intent(Intent.ACTION_TIME_TICK).addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND), 0,
UserHandle.ALL);
// now that we have initied the driver schedule the alarm
mClockReceiver= new ClockReceiver();
mClockReceiver.scheduleTimeTickEvent();
...
}
class ClockReceiver extends BroadcastReceiver {
public ClockReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_DATE_CHANGED);
mContext.registerReceiver(this, filter);
}
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
scheduleTimeTickEvent();
}
public void scheduleTimeTickEvent() {
final long currentTime = System.currentTimeMillis();
final long nextTime = 60000 * ((currentTime / 60000) + 1);
// Schedule this event for the amount of time that it would take to get to
// the top of the next minute.
final long tickEventDelay = nextTime - currentTime;
final WorkSource workSource = null; // Let system take blame for time tick events.
set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
0, mTimeTickSender, true, workSource);
}
}
/**
* Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC.
*
* <p>This method always returns UTC times, regardless of the system's time zone.
* This is often called "Unix time" or "epoch time".
* Use a {@link java.text.DateFormat} instance to format this time for display to a human.
*
* <p>This method shouldn't be used for measuring timeouts or
* other elapsed time measurements, as changing the system time can affect
* the results. Use {@link #nanoTime} for that.
*/
public static native long currentTimeMillis();
GETTIMEOFDAY(2) Linux Programmer's Manual GETTIMEOFDAY(2)
NAME
gettimeofday, settimeofday - get / set time
SYNOPSIS
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
settimeofday(): _BSD_SOURCE
DESCRIPTION
The functions gettimeofday() and settimeofday() can get and set the time as well as a timezone. The tv argument is a
struct timeval (as specified in <sys/time.h>):
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
and gives the number of seconds and microseconds since the Epoch (see time(2)). The tz argument is a struct timezone:
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of DST correction */
};
If either tv or tz is NULL, the corresponding structure is not set or returned.
AlarmManagerService 調用了 SystemClock 的 api setCurrentTimeMillis.
SystemClock.java
1
2
3
4
5
6
7
/**
* Sets the current wall time, in milliseconds. Requires the calling
* process to have appropriate permissions.
*
* @return if the clock was successfully set to the specified time.
*/
native public static boolean setCurrentTimeMillis(long millis);
SystemClock.java 調用了 native 方法
android_os_SystemClock.cpp
1
2
3
4
5
6
7
8
9
10
11
12
/*
* Set the current time. This only works when running as root.
*/
static int setCurrentTimeMillis(int64_t millis)
{
...
fd = open("/dev/alarm", O_RDWR);
...
res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
...
}