通过网络或直接本地获取到OTA升级包之后,通过程序就可开始Android的升级。本文描述这一过程。

在获取到OTA升级包之后,可以直接通过android.os.RecoverySystem.installPackage()开启OTA升级。

RecoverySystem.installPackage()是在API-8之后加入的,使用它需要权限:android.Manifest.permission.REBOOT

一、RecoverySystem#installPackage()的实现

RecoverySystem.installPackage()就是把传入的文件的文件名通过arg“--update_package=<filename>”【<filename>用具体文件代替】,调用bootCommand()实现。

bootCommand()的实现:

[java] view plain copy
  1. FileWritercommand=newFileWriter(COMMAND_FILE);
  2. try{
  3. command.write(arg);
  4. command.write("\n");
  5. }finally{
  6. command.close();
  7. }
  8. //Havingwrittenthecommandfile,goaheadandreboot
  9. PowerManagerpm=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
  10. m.reboot("recovery");

COMMAND_FILE 是“/cache/recovery/command”。bootCommand()也就是向/cache/recovery/command里把“--update_package=<filename>”写入,然后通过BinderIPC调用PowerManagerService的reboot(),并把“recovery”作为参数传入。

二、PowerManagerService#reboot的实现


PowerManagerService.reboot(reason: String)是通过启动ShutdownThread.reboot(mContext,finalReason, false)的执行实现。

执行顺序图如图所示,其中的值:

- reason: “recovery”;

- confirm: false;

- rebootOrShutdown的参数分别取值:reboot <- mReboot; reason<- mRebootReason;

最后调用的Power.reboot(),通过JNI调用它的c实现。

在Power.java的JNI实现在android_os_power.cpp中。


三、Power.reboot的Native实现


Power.reboot()是通过android_os_Power_reboot实现【frameworks/base/core/jni/android_os_power.cpp中】

[cpp] view plain copy
  1. staticvoidandroid_os_Power_reboot(JNIEnv*env,jobjectclazz,jstringreason)
  2. {
  3. sync();
  4. #ifdefHAVE_ANDROID_OS
  5. if(reason==NULL){
  6. reboot(RB_AUTOBOOT);
  7. }else{
  8. constchar*chars=env->GetStringUTFChars(reason,NULL);
  9. __reboot(LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,
  10. LINUX_REBOOT_CMD_RESTART2,(char*)chars);
  11. env->ReleaseStringUTFChars(reason,chars);//Incaseitfails.
  12. }
  13. jniThrowIOException(env,errno);
  14. #endif
  15. }

通过系统调用__reboot,嵌入内核,实现reboot。

在内核态,进入sys_reboot系统定义。

四、sys_reboot的定义与实现


sys_reboot的定义与实现要看内核中的代码

[cpp] view plain copy
  1. //kernel/kernel/sys.c
  2. SYSCALL_DEFINE4(reboot,int,magic1,int,magic2,unsignedint,cmd,
  3. void__user*,arg)
  4. //kernel/include/linux/syscalls.h
  5. #define__SYSCALL_DEFINEx(x,name,...)\
  6. asmlinkagelongsys##name(__SC_DECL##x(__VA_ARGS__))
  7. #defineSYSCALL_DEFINEx(x,sname,...)\
  8. __SYSCALL_DEFINEx(x,sname,__VA_ARGS__)
  9. #defineSYSCALL_DEFINE4(name,...)SYSCALL_DEFINEx(4,_##name,__VA_ARGS__)

所以,sys.c中的SYSCALL_DEFINE4(reboot, ...)就实现了sys_reboot()

SYSCALL_DEFINE4(reboot,...)中对magic1magic2进行判别,只有符合的magic1及和magic2才会处理,否则直接返回。

对cmdLINUX_REBOOT_CMD_RESTART2:把reboot的reason从用户态拷贝到内核态,调用kernel_restart()执行。

kernel_restart(char* cmd)先调用kernel_restart_prepare(cmd);然后调用machine_restart(cmd);

[cpp] view plain copy
  1. //kernel/kernel/sys.c
  2. voidkernel_restart_prepare(char*cmd)
  3. {
  4. blocking_notifier_call_chain(&reboot_notifier_list,SYS_RESTART,cmd);
  5. system_state=SYSTEM_RESTART;
  6. device_shutdown();
  7. sysdev_shutdown();
  8. }

[cpp] view plain copy
  1. //kernel/arch/arm/kernel/process.c
  2. voidmachine_restart(char*cmd)
  3. {
  4. arm_pm_restart(reboot_mode,cmd);
  5. }

arm_pm_restart指向具体平台定义的机器重启的函数指针,原型是void(*arm_pm_restart)(char str, const char *cmd)。

具体实现与所采用的特定平台相关,这里不再讲述。

总结


本文描述了Android中对OTA升级发起的过程,从Framework到JNI,再到Kernel层,层层关系的分析,看到所谓的OTA升级的发起,就是通过向/cache/recovery/command里把“--update_package=<filename>”写入,然后通过系统调用转入内核态执行系统调用,实现机器重启,完成OTA升级的全过程。

重启之后,进入Recovery模式的过程在后面的专题中再讨论。

更多相关文章

  1. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  2. Android(安卓)自定义View需要重写ondraw()等方法
  3. Android调用系统内部的下载程序下载文件(二)
  4. 基于Android的Linux内核的电源管理:Early Suspend
  5. Android(安卓)--- 应用中全局变量的设置
  6. Android(安卓)WiFi扫描
  7. Android(安卓)自定义View学习(十一)——ViewGroup测量知识学习
  8. Android(安卓)N之hasSystemFeature
  9. ViewPage第三课自定义viewpage

随机推荐

  1. Android用Websocket实现聊天室
  2. cm-14.1 Android系统启动过程分析(四)-Laun
  3. Android中Gravity中的一些值都是些什么意
  4. Android之ButterKnife用法详解
  5. 【Android】 Painless Thread
  6. 安卓手机恶意代码——Samsapo
  7. 《第一行代码--Android》读书笔记之内容
  8. Android MediaPlayer音频播放器详解
  9. 实现对特定内容改变字体颜色的TextView
  10. android自定义按钮控件样式