alarm system call

First, the calling process alarm

1. alarm setup process

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);
}


frameworks/base/services/core/java/com/android/server/AlarmManagerService.java

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);

frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp

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);
}

By setting the kernel system call time:

SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr)

 

2. Android by poll upper've been listening ararm, upon receipt of the notification, the corresponding event distribution.

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();
        }
    }
 }

Only type 0 or type 2 alarm customers wake-up system. You can find wake-up alarm system according to printing information, such as

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}}

 

Second, the system calls the function function set timerfd

1. man timerfd_create

NAME
       timerfd_create, timerfd_settime, timerfd_gettime - timers that notify via file descriptors

SYNOPSIS
       #include <sys/timerfd.h>

       int timerfd_create(int clockid, int flags);

       int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);

       int timerfd_gettime(int fd, struct itimerspec *curr_value);

2. Use the demo

#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>  /* Definition of uint64_t */

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

static void print_elapsed_time(void)
{
    static struct timespec start;
    static int first_call = 1;
    struct timespec curr;
    int secs, nsecs;

    if (first_call) {
        first_call = 0;
        if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) {
            handle_error("clock_gettime");       
        }
    }

    if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) {
        handle_error("clock_gettime"); 
    }

    secs = curr.tv_sec - start.tv_sec;
    nsecs = curr.tv_nsec - start.tv_nsec;
    if (nsecs < 0) {
        secs--;
        nsecs += 1000000000;
    }
    printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
}

int main(int argc, char *argv[])
{
    struct itimerspec new_value;
    int max_exp, fd;
    struct timespec now;
    uint64_t exp, tot_exp;
    ssize_t s;

    if ((argc != 2) && (argc != 4)) {
       fprintf(stderr, "%s init-secs [interval-secs max-exp]\n", argv[0]);
       exit(EXIT_FAILURE);
    }

    if (clock_gettime(CLOCK_REALTIME, &now) == -1) {
        handle_error("clock_gettime");    
    }

   /* Create a CLOCK_REALTIME absolute timer with initial
      expiration and interval as specified in command line */
   new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
   new_value.it_value.tv_nsec = now.tv_nsec;
   if (argc == 2) {
        new_value.it_interval.tv_sec = 0;
        max_exp = 1;
    } else {
        new_value.it_interval.tv_sec = atoi(argv[2]);
        max_exp = atoi(argv[3]);
    }
    new_value.it_interval.tv_nsec = 0;

    /* begin use these functions */
    fd = timerfd_create(CLOCK_REALTIME, 0);
    if (fd == -1)
        handle_error("timerfd_create");

    if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
        handle_error("timerfd_settime");

    print_elapsed_time();
    printf("timer started\n");

    for (tot_exp = 0; tot_exp < max_exp;) {
        s = read(fd, &exp, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
            handle_error("read");
        tot_exp += exp;
        print_elapsed_time (); 
        the printf ( " Read:% LLU; LLU Total =% \ n- " , (unsigned Long  Long ) exp, (unsigned Long  Long ) tot_exp); 
    } 

    Exit (of EXIT_SUCCESS); 
} 

/ * 
$. 3. 1 ./pp The first timer 100 @ 3s, after the notification once every one second. 
0.000: Timer Started 
3.002: Read:. 1;. 1 Total = 
4.001: Read:. 1; 2 Total = 
5.000: Read:. 1;. 3 Total = 
6.001: Read:. 1; Total =. 4 
^ the Z 
[. 1] + the Stopped ./pp 100. 1. 3 
$ FG 
./pp. 3. 1 100 
21.808: Read: 15; // the Ctrl + Total =. 19 is suspended after the Z app, app not receive the notification. 
22.000: read: 1; total = 20
23.001: read: 1; total=21
^C
*/

 

Three, RTC clock

1. alarm timer underlayer using rtc

//kernel/time/alarmtimer.c

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,
    },
};

 

Four, Android system, some use

1. Battery status update

static void wakealarm_set_interval(int interval) {
    itval.it_interval.tv_sec = interval;
    itval.it_interval.tv_nsec = 0;
    itval.it_value.tv_sec = interval;
    itval.it_value.tv_nsec = 0;
    timerfd_settime(wakealarm_fd, 0, &itval, NULL);
}

void healthd_battery_update_internal(bool charger_online) {
    // Fast wake interval when on charger (watch for overheat);
    // slow wake interval when on battery (watch for drained battery).
    int ? new_wake_interval = charger_online healthd_config.periodic_chores_interval_fast   // charging 1min rtc wakeup time 
                                        : healthd_config.periodic_chores_interval_slow; // wake-up time 10min rtc non-rechargeable 
}

 

Guess you like

Origin www.cnblogs.com/hellokitty2/p/11748262.html