Android从上层到底层完整流程.docx

上传人:b****5 文档编号:28601419 上传时间:2023-07-19 格式:DOCX 页数:8 大小:18.48KB
下载 相关 举报
Android从上层到底层完整流程.docx_第1页
第1页 / 共8页
Android从上层到底层完整流程.docx_第2页
第2页 / 共8页
Android从上层到底层完整流程.docx_第3页
第3页 / 共8页
Android从上层到底层完整流程.docx_第4页
第4页 / 共8页
Android从上层到底层完整流程.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

Android从上层到底层完整流程.docx

《Android从上层到底层完整流程.docx》由会员分享,可在线阅读,更多相关《Android从上层到底层完整流程.docx(8页珍藏版)》请在冰豆网上搜索。

Android从上层到底层完整流程.docx

Android从上层到底层完整流程

Android上层界面到内核代码的完整的流程分析,以alarm为例子

很久之前写的一个流程文档,从上层界面一直调用到内核的过程,最近同事跟我要,我看了下又在整理了下,纯属个人分析(不过都运行验证过),不对的请大牛指出。

Alarm调用流程,alarm的流程实现了从上层应用一直到下面driver的调用流程,下面简单阐述:

涉及代码;

./packages/apps/DeskClock/src//android/deskclock/Alarms.java

./frameworks/base/core/java/android/app/AlarmManager.java

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

./frameworks/base/services/jni/_android_server_AlarmManagerService.cpp

./kernel/kernel/drivers/rtc/alarm-dev.c

./kernel/kernel/include/linux/android_alarm.h

./kernel/kernel/drivers/rtc/alarm.c

./kernel/kernel/drivers/rtc/interface.c

./kernel/kernel/drivers/rtc/rtc-pcf8563.c

/packages/apps/DeskClock/src//android/deskclock/AlarmReceiver.java

./kernel/arch/arm/configs/mmp2_android_defconfig

./kernel/kernel/kernel/.config  点击Clock应用程序,然后设置新闹钟,会调到Alarms.java里面的

publicstaticlongsetAlarm(Contextcontext,Alarmalarm){

....setNextAlert(context);

....

}然后这里面也会调用到 

publicstaticvoidsetNextAlert(finalContextcontext){

       if(!

enableSnoozeAlert(context)){

           Alarmalarm=calculateNextAlert(context);//new一个新的alarm

           if(alarm!

=null){

               enableAlert(context,alarm,alarm.time);

           }else{

               disableAlert(context);

           }

       }

   }然后继续调用到

privatestaticvoidenableAlert(Contextcontext,finalAlarmalarm,finallongatTimeInMillis){

.......

am.set(AlarmManager.RTC_WAKEUP,atTimeInMillis,sender);//这里是RTC_WAKEUP,这就保证了即使系统睡眠了,都能唤醒,闹钟工作(android平台关机闹钟好像不行)

.....

}然后就调用到了AlarmManager.java里面方法

   publicvoidset(inttype,longtriggerAtTime,PendingIntentoperation){

       try{

           mService.set(type,triggerAtTime,operation);

       }catch(RemoteExceptionex){

       }

   }然后就调用到了AlarmManagerService.java 里面方法

publicvoidset(inttype,longtriggerAtTime,PendingIntentoperation){

       setRepeating(type,triggerAtTime,0,operation);

   }然后继续调用

publicvoidsetRepeating(inttype,longtriggerAtTime,longinterval,

           PendingIntentoperation)

{

.....

synchronized(mLock){

           Alarmalarm=newAlarm();

           alarm.type=type;

           alarm.when=triggerAtTime;

           alarm.repeatInterval=interval;

           alarm.operation=operation;

           //Removethisalarmifalreadyscheduled.

           removeLocked(operation);

           if(localLOGV)Slog.v(TAG,"set:

"+alarm);

           intindex=addAlarmLocked(alarm);

           if(index==0)

{

               setLocked(alarm);

           }

       }

   }然后就调用到

privatevoidsetLocked(Alarmalarm){

   ......//mDescriptor这里的文件是/dev/alarm   set(mDescriptor,alarm.type,alarmSeconds,alarmNanoseconds);     

.....

}这里就调用到jni了

privatenativevoidset(intfd,inttype,longseconds,longnanoseconds);这就调用到了_android_server_AlarmManagerService.cpp里面

staticJNINativeMethodsMethods[]={

    /*name,signature,funcPtr*/

   {"init","()I",(void*)android_server_AlarmManagerService_init},

   {"close","(I)V",(void*)android_server_AlarmManagerService_close},

   {"set","(IIJJ)V",(void*)android_server_AlarmManagerService_set},

   {"waitForAlarm","(I)I",(void*)android_server_AlarmManagerService_waitForAlarm},

   {"setKernelTimezone","(II)I",(void*)android_server_AlarmManagerService_setKernelTimezone},

};

set对应的是android_server_AlarmManagerService_set,具体是

staticvoidandroid_server_AlarmManagerService_set(JNIEnv*env,jobjectobj,jintfd,jinttype,jlongseconds,jlongnanoseconds)

{

#ifHAVE_ANDROID_OS

   structtimespects;

   ts.tv_sec=seconds;

   ts.tv_nsec=nanoseconds;

   

   intresult=ioctl(fd,ANDROID_ALARM_SET(type),&ts);

   if(result<0)

   {

       LOGE("Unabletosetalarmto%lld.%09lld:

%s\n",seconds,nanoseconds,strerror(errno));

   }

#endif

}然后ioctl就调用到了alarm-dev.c

staticlongalarm_ioctl(structfile*file,unsignedintcmd,unsignedlongarg)

{

....

   caseANDROID_ALARM_SET(0):

      if(copy_from_user(&new_alarm_time,(void__user*)arg,sizeof(new_alarm_time))){         rv=-EFAULT;

         gotoerr1;

      }

from_old_alarm_set:

      spin_lock_irqsave(&alarm_slock,flags);

      pr_alarm(IO,"alarm%dset%ld.%09ld\n",alarm_type,

         new_alarm_time.tv_sec,new_alarm_time.tv_nsec);

      alarm_enabled|=alarm_type_mask;

      alarm_start_range(&alarms[alarm_type],

         timespec_to_ktime(new_alarm_time),

         timespec_to_ktime(new_alarm_time));

      spin_unlock_irqrestore(&alarm_slock,flags);

      if(ANDROID_ALARM_BASE_CMD(cmd)!

=ANDROID_ALARM_SET_AND_WAIT(0)&&cmd!

=ANDROID_ALARM_SET_AND_WAIT_OLD)         break;

      /*fallthough*/

....

caseANDROID_ALARM_SET_RTC:

      if(copy_from_user(&new_rtc_time,(void__user*)arg,

         sizeof(new_rtc_time))){

         rv=-EFAULT;

         gotoerr1;

      }

      rv=alarm_set_rtc(new_rtc_time);

      spin_lock_irqsave(&alarm_slock,flags);

      alarm_pending|=ANDROID_ALARM_TIME_CHANGE_MASK;

      wake_up(&alarm_wait_queue);

      spin_unlock_irqrestore(&alarm_slock,flags);

      if(rv<0)

         gotoerr1;

      break;

....

}然后这边就调用到了alarm_start_range设置闹钟,alarm_set_rtc设置RTC这两个函数在android_alarm.h声明,在alarm.c里实现。

这是android_alarm.h里面的声明

voidalarm_start_range(structalarm*alarm,ktime_tstart,ktime_tend);

intalarm_try_to_cancel(structalarm*alarm);

intalarm_cancel(structalarm*alarm);

ktime_talarm_get_elapsed_realtime(void);/*setrtcwhilepreservingelapsedrealtime*/

intalarm_set_rtc(conststructtimespects);下面看alarm.c里面实现:

intalarm_set_rtc(structtimespecnew_time)

{

....

ret=rtc_set_time(alarm_rtc_dev,&rtc_new_rtc_time);

....

}

alarm.c 里面实现了alarm_suspend alarm_resume函数,就是如果系统没有suspend的时候,设置闹钟并不会往rtc芯片的寄存器上写数据,因为不需要唤醒系统,所以闹钟数据时间什么的就通过上层写到设备文件/dev/alarm,里面就可以了,AlarmThread会不停的去轮寻下一个时间有没有闹钟,直接从设备文件/dev/alarm里面读取。

第二种,系统要是进入susupend的话,alarm的alarm_suspend就会写到下层的rtc芯片的寄存器上去,然后即使系统suspend之后,闹钟通过rtc也能唤醒系统,这里就调用到了interface.c里面  //这里面intrtc_set_alarm(structrtc_device*rtc,structrtc_wkalrm*alarm)差不多也是跟下面一样

intrtc_set_time(structrtc_device*rtc,structrtc_time*tm)

{

....

   err=rtc->ops->set_time(rtc->dev.parent,tm);

....

}然后set_time就看到具体的是那个RTC芯片,这边我们是rtc-pcf8563.c

staticconststructrtc_class_opspcf8563_rtc_ops={

   .read_time   =pcf8563_rtc_read_time,

   .set_time   =pcf8563_rtc_set_time,

   .read_alarm   =pcf8563_rtc_read_alarm,

   .set_alarm   =pcf8563_rtc_set_alarm,

};然后就到了

staticintpcf8563_rtc_set_time(structdevice*dev,structrtc_time*tm)

{

   unsignedcharbuf[TIME_NUM];

   intret;

   ret=data_calc(buf,tm,TIME_NUM);

   if(ret<0)

      gotoout;

   ret=i2c_smbus_write_i2c_block_data(pcf8563_info->client,PCF8563_RTC_SEC,TIME_NUM,buf); //这边就调用i2c统一接口,往pcf8563rtc芯片寄存器里面写出数据

out:

   returnret;

}到此,闹钟时间就已经写到rtc芯片的寄存器里面,第二个参数就是寄存器的名字,后面的buf就是要写入的时间,rtc芯片是额外供电的,所以系统suspend之后,系统kernel都关了,但是rtc里面还有电,寄存器里面数据还是有的(掉电就会丢失数据),所以闹钟到了,通过硬件中断机制就可以唤醒系统。

上面那个rtc下面有几十个rtc芯片驱动代码,没有结构基本一样,都有基本操作函数,注册函数,都是对各自芯片上特有的寄存器操作,为什么调用的是pcf8563rtc呢?

这个要看你系统用的是那个芯片,这个可以通过./kernel/kernel/kernel/.config 查看,这边的pcf8563rtc是当前系统正在使用的芯片型号 

#CONFIG_RTC_DRV_ISL1208isnotset

#CONFIG_RTC_DRV_X1205isnotset

CONFIG_RTC_DRV_PCF8563=y

#CONFIG_RTC_DRV_PCF8583isnotset

#CONFIG_RTC_DRV_M41T80isnotset下面是系统唤醒之后,闹钟怎么工作的流程,简单阐述系统没有suspend的话直接走下面流程,如果suspend的话会被RTC唤醒,然后还是走下面的流程

 privateclassAlarmThreadextendsThread

   {

       publicAlarmThread()

       {

           super("AlarmManager");

       }

       

       publicvoidrun()

       {

      while(true)

           {

      intresult=waitForAlarm(mDescriptor);//这里调用jni调用staticjintandroid_server_AlarmManagerService_waitForAlarm,主要还是对/dev/alarm 操作

      ....

      Alarmalarm=it.next();

                       try{

                           if(localLOGV)Slog.v(TAG,"sendingalarm"+alarm);

                           alarm.operation.send(mContext,0,                                   mBackgroundIntent.putExtra(

                                           Intent.EXTRA_ALARM_COUNT,alarm.count),

                                   mResultReceiver,mHandler);

      ....

      }

   }

     }

staticjintandroid_server_AlarmManagerService_waitForAlarm(JNIEnv*env,jobjectobj,jintfd)

{

#ifHAVE_ANDROID_OS

   intresult=0;

   

   do

   {

      result=ioctl(fd,ANDROID_ALARM_WAIT);

   }while(result<0&&errno==EINTR);

   

   if(result<0)

   {

       LOGE("Unabletowaitonalarm:

%s\n",strerror(errno));

       return0;

   }

   

   returnresult;

#endif

}

AlarmManagerService 里面有个AlarmThread会一直轮询/dev/alarm文件,如果打开失败就直接返回,成功就会做一些动作,比如查找时间最近的alarm,比如睡眠被闹钟唤醒的时候,这边就发一个intent出去,然后在AlarmReceiver.java里面弹出里面会收到就会调用下面的

      context.startActivity(alarmAlert);然后弹出alarm 这个界面

       Classc=AlarmAlert.class;其中publicclassAlarmAlertextendsAlarmAlertFullScreen 所以系统睡眠之后被alarm唤醒弹出的alarm就是这边start的

publicclassAlarmReceiverextendsBroadcastReceiver{

   /**IfthealarmisolderthanSTALE_WINDOW,ignore. It

       isprobablytheresultofatimeortimezonechange*/   privatefinalstaticintSTALE_WINDOW=30*60*1000;

   Override

   publicvoidonReceive(Contextcontext,Intentintent){

   .........

       IntentalarmAlert=newIntent(context,c);

       alarmAlert.putExtra(Alarms.ALARM_INTENT_EXTRA,alarm);

       alarmAlert.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK

               |Intent.FLAG_ACTIVITY_NO_USER_ACTION);

       context.startActivity(alarmAlert);

   ........

}到这里alarm就显示出来了我个人添加的log,验证了流程,suspend和不suspend的时候alarm的区别跟上面说的一样

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 可爱清新

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1