• Android OTA升级(2):开启升级过程



    http://blog.csdn.net/thl789/article/details/8743768


    田海立@CSDN

    2013-3-31

    通过网络或直接本地获取到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()的实现:

    1. FileWriter command= new FileWriter(COMMAND_FILE);  
    2. try {  
    3.    command.write(arg);  
    4.    command.write(" ");  
    5. finally {  
    6.    command.close();  
    7. }  
    8.   
    9. // Having writtenthe command file, go ahead and reboot  
    10. PowerManager pm =(PowerManager) context.getSystemService(Context.POWER_SERVICE);  
    11. 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中】

    1. static void android_os_Power_reboot(JNIEnv *env, jobject clazz,jstring reason)  
    2. {  
    3.     sync();  
    4. #ifdef HAVE_ANDROID_OS  
    5.     if (reason == NULL) {  
    6.        reboot(RB_AUTOBOOT);  
    7.     } else {  
    8.         const char *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);  // In case it fails.  
    12.     }  
    13.     jniThrowIOException(env,errno);  
    14. #endif  
    15. }  

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

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

    四、sys_reboot的定义与实现


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

    1. // kernel/kernel/sys.c  
    2. SYSCALL_DEFINE4(reboot, int, magic1, int,magic2, unsigned int, cmd,  
    3.                                 void__user *, arg)  
    4.    
    5. //kernel/include/linux/syscalls.h  
    6. #define __SYSCALL_DEFINEx(x, name, ...)                                                                    
    7.                 asmlinkagelong sys##name(__SC_DECL##x(__VA_ARGS__))  
    8.    
    9. #define SYSCALL_DEFINEx(x, sname, ...)                                                       
    10.                 __SYSCALL_DEFINEx(x,sname, __VA_ARGS__)  
    11.    
    12. #define SYSCALL_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); 

    1. // kernel/kernel/sys.c  
    2. void kernel_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. }  
    1. //kernel/arch/arm/kernel/process.c  
    2. void machine_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模式的过程在后面的专题中再讨论。


  • 相关阅读:
    jupyter安装出现问题:安装后无法打开
    GitHub上传文件问题总结
    GitHub上传文件夹
    ELK 搭建
    mysql 开放远程连接权限连不上
    mysql linux下安装
    多个springboot项目部署到tomcat,Error deploying web application archive
    mysql 新增时,唯一索引冲突时更新
    日期计算
    mysql 忘记密码
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645442.html
Copyright © 2020-2023  润新知