AlarmManagerService的hal层分析

来源:互联网 发布:python兼职 编辑:程序博客网 时间:2024/05/16 16:14

之前我们分析过AlarmManagerService了,这里我们主要分析下其hal层。

我们先来看onStart这段代码:

    public void onStart() {        mNativeData = init();

这个init函数是native函数,是用来初始化hal层的。mNativeData数据就是从hal层函数返回。


一、有alarm设备

我们看下android_server_AlarmManagerService_init函数,它先调用了init_alarm_driver函数,只要返回不为0,函数就返回。

static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject){    jlong ret = init_alarm_driver();    if (ret) {        return ret;    }    return init_timerfd();}

我们先来看init_alarm_driver函数

static jlong init_alarm_driver(){    int fd = open("/dev/alarm", O_RDWR);    if (fd < 0) {        ALOGV("opening alarm driver failed: %s", strerror(errno));        return 0;    }    AlarmImpl *ret = new AlarmImplAlarmDriver(fd);    return reinterpret_cast<jlong>(ret);}

只要设备支持alarm,就是有dev/alarm这个目录,那我们就把这个fd传入AlarmImplAlarmDriver,然后返回AlarmImplAlarmDriver的对象指针。


我们再来看AlarmManagerService在setLocked中调用set这个native函数,就是设置alarm。

    private void setLocked(int type, long when) {        if (mNativeData != 0) {            // The kernel never triggers alarms with negative wakeup times            // so we ensure they are positive.            long alarmSeconds, alarmNanoseconds;            if (when < 0) {                alarmSeconds = 0;                alarmNanoseconds = 0;            } else {                alarmSeconds = when / 1000;                alarmNanoseconds = (when % 1000) * 1000 * 1000;            }                        set(mNativeData, type, alarmSeconds, alarmNanoseconds);        }
就是把之前的mNativeData的数据传下来,然后调用器set函数。

static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds){    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);    struct timespec ts;    ts.tv_sec = seconds;    ts.tv_nsec = nanoseconds;    int result = impl->set(type, &ts);    if (result < 0)    {        ALOGE("Unable to set alarm to %lld.%09lld: %s\n",              static_cast<long long>(seconds),              static_cast<long long>(nanoseconds), strerror(errno));    }}
之前的mNativeData就是下面这个类的对象

class AlarmImplAlarmDriver : public AlarmImpl{public:    AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }    int set(int type, struct timespec *ts);    int setTime(struct timeval *tv);    int waitForAlarm();};
最后设置alarm,是调用了ioctl。

int AlarmImplAlarmDriver::set(int type, struct timespec *ts){    return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);}

waitForAlarm函数也是调用ioctl

int AlarmImplAlarmDriver::waitForAlarm(){    return ioctl(fds[0], ANDROID_ALARM_WAIT);}


二、没有alarm设备

我们再来看看,假如不支持alarm,hal层又会怎么处理

static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject){    jlong ret = init_alarm_driver();    if (ret) {        return ret;    }    return init_timerfd();}

在调用init函数的时候,如果不支持alarm,就会调用init_timerfd函数:

static jlong init_timerfd(){    int epollfd;    int fds[N_ANDROID_TIMERFDS];    epollfd = epoll_create(N_ANDROID_TIMERFDS);//epoll    if (epollfd < 0) {        ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS,                strerror(errno));        return 0;    }    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {        fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);//创建定时器        if (fds[i] < 0) {            ALOGV("timerfd_create(%u) failed: %s",  android_alarm_to_clockid[i],                    strerror(errno));            close(epollfd);            for (size_t j = 0; j < i; j++) {                close(fds[j]);            }            return 0;        }    }    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());//构造AlarmImplTimerFd对象    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {        epoll_event event;        event.events = EPOLLIN | EPOLLWAKEUP;        event.data.u32 = i;        int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);//把各个定时器fd加入epoll        if (err < 0) {            ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));            delete ret;            return 0;        }    }    struct itimerspec spec;    memset(&spec, 0, sizeof(spec));    /* 0 = disarmed; the timerfd doesn't need to be armed to get       RTC change notifications, just set up as cancelable */    int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],            TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);    if (err < 0) {        ALOGV("timerfd_settime() failed: %s", strerror(errno));        delete ret;        return 0;    }    return reinterpret_cast<jlong>(ret);}

这个函数,主要创建了几个定时器,然后将定时器fd加入epoll。并且mNativeData返回的是AlarmImplTimerFd对象

class AlarmImplTimerFd : public AlarmImpl{public:    AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) :        AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { }    ~AlarmImplTimerFd();    int set(int type, struct timespec *ts);    int setTime(struct timeval *tv);    int waitForAlarm();private:    int epollfd;    int rtc_id;};

我们来看set函数,这个函数就是调用了定时器的设置时间。

int AlarmImplTimerFd::set(int type, struct timespec *ts){    if (type > ANDROID_ALARM_TYPE_COUNT) {        errno = EINVAL;        return -1;    }    if (!ts->tv_nsec && !ts->tv_sec) {        ts->tv_nsec = 1;    }    /* timerfd interprets 0 = disarm, so replace with a practically       equivalent deadline of 1 ns */    struct itimerspec spec;    memset(&spec, 0, sizeof(spec));    memcpy(&spec.it_value, ts, sizeof(spec.it_value));    return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);}

最后我们会在waitForAlarm函数中,使用epoll_wait,当定时器超时就有事件。

int AlarmImplTimerFd::waitForAlarm(){    epoll_event events[N_ANDROID_TIMERFDS];    int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);    if (nevents < 0) {        return nevents;    }    int result = 0;    for (int i = 0; i < nevents; i++) {        uint32_t alarm_idx = events[i].data.u32;        uint64_t unused;        ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));        if (err < 0) {            if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {                result |= ANDROID_ALARM_TIME_CHANGE_MASK;            } else {                return err;            }        } else {            result |= (1 << alarm_idx);        }    }    return result;}


三、总结

AlarmManagerService的hal层既考虑的支持alarm和不支持alarm,当支持alarm的时候,就是调用ioctl。不支持就是创建定时器,并且将fd加入到epoll机制。




1 0
原创粉丝点击