android系统中alarm驱动框架分析

本文深入剖析了Android系统的Alarm框架,从AlarmManager类的使用,到AlarmManagerService的内部实现,再到JNI层与硬件驱动的交互。文章详细解释了如何设置一次性与重复性的闹钟,并着重介绍了alarm驱动层的工作原理,包括alarm-dev.c和rtc驱动的交互,以及内核中的注册和初始化过程。

专题一alarm

第一课、

1、 功能:一般用作闹钟

2、 工作流程:

App->获取系统服务(alarm service->返回特定类型的对象(Alarm Manager->

启动闹钟->定时时间到后通过广播通知app(也可以通过activityservice通知)->广播接收器(broadcast receiver->进行处理

二、分析Alarm Manager

进入下面网站:

http://www.android-doc.com/   -》点击API文档-android.app-classes-Alarm Manager

-public methods

 

Schedule an alarm起到一个一次性的定时器

void set(int type, long triggerAtMillis, PendingIntent operation)

Schedule a repeatingalarm启动一个重复性的定时器

Void setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)

 

参数:

1type可以取值为:One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC, or RTC_WAKEUP一般使用RTC_WAKEUP,表示即使android即使处于休眠状态,一旦定时器超时也会触发事件/

2triggerAtMillis为超时时间,单位是ms

3operation:当定时器超时后执行什么事件,一般为发烧广播/4intervalMillis:为重复闹钟俩次响铃的时间间隔

 

三、开始编写app

最后过滤打印信息:adb logcat -s alarm

 

第二课

整体框架:

1、进入AlarmManager.java (frameworks\base\core\java\android\app)开始分析

分析过程(从启动函数开始分析):

///////////////AlarmManager////////////////////////////////////////////////////

public void set()   390

-private void setImpl()

-mService.set();

/////////////////进入AlarmManagerService.java////////////////////////////////////////

-》此后会调用AlarmManagerService.java780set函数 

进入AlarmManagerService

-void setImpl()

-setImplLocked()

-rescheduleKernelAlarmsLocked();

-setLocked()

////////////开始进入jni///////////////////////////////////////////////路径如下

com_android_server_AlarmManagerService.cpp(frameworks\base\services\core\jni)

/////////////////////////////////////////////////////////////////////////////////////////////

 -set()    其函数定义:private native voidset();

-void android_server_AlarmManagerService_set()

-impl->set(type, &ts);  //分析此函数,先分析impl对象

-class AlarmImpl{  }

-virtual int set(int type, struct timespec *ts) = 0;  //因为是虚函数,所以set AlarmImpl的继承类实现

-class AlarmImplAlarmDriver : public AlarmImpl{}

-int AlarmImplAlarmDriver::set(int type, struct timespec *ts)

-ioctl(fds[0], ANDROID_ALARM_SET(type), ts);此函数中的fds[0]指的是下面open函数获取的fd,在source insight中收索open函数即可找到

static jlonginit_alarm_driver()

{

    int fd = open("/dev/alarm",O_RDWR);

    if (fd < 0) {

        ALOGV("opening alarm driverfailed: %s", strerror(errno));

        return 0;

    }

    AlarmImpl *ret = newAlarmImplAlarmDriver(fd);

    return reinterpret_cast<jlong>(ret);

}

/////////////////开始进入alarm驱动层(alarm-dev.c//////////////////////////////////////

-static long alarm_ioctl()

-case ANDROID_ALARM_SET_RTC:  //开始设置

-alarm_set_rtc(new_rtc_time);  //进入分析

-rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);  //进入此函数

//////////////////进入rtc驱动///////////////////////////////////////////////////////////

rtc->ops->set_time(rtc->dev.parent,tm);  //开始操作rtc驱动

2分析alarm启动

2.1分析private void setImplLocked函数

Alarm即闹钟

Batch:闹钟容器

一个系统种一定有多个batch,每个batch中可以有多个闹钟

 

3查询闹钟是否超时过程:

当系统中的硬件闹钟响起时,就会与batch中的alarm进行比较,如果有合适的,就会激活batch中的alarm,最终调用alalrm的操作函数

 

///////////////进入AlarmManagerService.java/////////////////////////

-private class AlarmThread extends Thread1673行)

-waitForAlarm(mNativeData);  //会调用jni中的waitForAlarm函数,发生阻塞,直到有闹钟超时函数返回

///////////////////进入jniandroid_server_AlarmManagerService.cpp //////////////

-static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*,jobject, jlong nativeData)

-result = impl->waitForAlarm();

-int AlarmImplAlarmDriver::waitForAlarm()

-ioctl(fds[0], ANDROID_ALARM_WAIT); 调用alarm-dev.c驱动中的ioctl函数

////////////////进入内核驱动alarm_dev.c//////////////////////////////////////////

-static long alarm_ioctl(struct file *file, unsigned int cmd, unsignedlong arg)

-case ANDROID_ALARM_WAIT: 

-rv = alarm_pending;   //获取alarm_pending的值,这个值其实就是alarmmask

-return rv;

 

 

 

第二课:内核驱动分析

1alalrm_dev.c分析

-static int __init alarm_dev_init(void)  //入口函数

-misc_register(&alarm_device); //注册为混扎设备驱动

-static struct miscdevice alarm_device = {

-.fops = &alarm_fops,   //操作函数集

-static const struct file_operations alarm_fops = {

       .owner = THIS_MODULE,

       .unlocked_ioctl = alarm_ioctl,    //ioctl为给用户提供的接口函数

       .open = alarm_open,

       .release = alarm_release,

};

-alarm_ioctl,    //ioctl为给用户提供的接口函数

-case ANDROID_ALARM_SET_RTC:  //开始设置一个新的闹钟

-alarm_set_rtc(new_rtc_time);  //进入分析

-rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);  //进入此函数  设置闹钟相应时间

-rtc->ops->set_time(rtc->dev.parent, tm);  //开始操作rtc驱动,在rtc-s3c.cstruct rtc_class_ops s3c_rtcops中的set_time函数

/////////开始进入rtc-s3c.c static const struct rtc_class_opss3c_rtcops = {}///////////

-.set_time= s3c_rtc_settime,   //设置设置alalrm时间

 

 

2rtc-s3c.c分析

-static int __inits3c_rtc_init(void)  //入口函数

-platform_driver_register(&s3c_rtc_driver);  //注册平台设备驱动

-static struct platform_drivers3c_rtc_driver = {

       .probe           =s3c_rtc_probe,  //主要分析probe函数

       .remove        =__devexit_p(s3c_rtc_remove),

       .suspend       =s3c_rtc_suspend,

       .resume        =s3c_rtc_resume,

       .id_table=s3c_rtc_driver_ids,

       .driver           ={

              .name    = "s3c-rtc",

              .owner   = THIS_MODULE,

       },

};

-s3c_rtc_probe,  //主要分析probe函数

-s3c_rtc_enable(pdev, 1);rtc硬件初始化

-s3c_rtc_gettime(NULL, &rtc_tm);获取当前时间

-rtc = rtc_device_register("s3c",&pdev->dev, &s3c_rtcops, THIS_MODULE); 注册rtc设备,注意一下注册的操作函数集s3c_rtcops,

-static conststruct rtc_class_ops s3c_rtcops = {

       .read_time    = s3c_rtc_gettime,

       .set_time      =s3c_rtc_settime,   //设置时间

       .read_alarm  = s3c_rtc_getalarm,

       .set_alarm    = s3c_rtc_setalarm,

       .alarm_irq_enable = s3c_rtc_setaie,

};

-.set_time= s3c_rtc_settime,   //设置设置alalrm时间

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值