田海立@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()的实现:

        FileWriter command= new FileWriter(COMMAND_FILE);        try {           command.write(arg);           command.write("\n");        } finally {           command.close();        }         // Having writtenthe command file, go ahead and reboot        PowerManager pm =(PowerManager) context.getSystemService(Context.POWER_SERVICE);       pm.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中】

static void android_os_Power_reboot(JNIEnv *env, jobject clazz,jstring reason){    sync();#ifdef HAVE_ANDROID_OS    if (reason == NULL) {       reboot(RB_AUTOBOOT);    } else {        const char *chars =env->GetStringUTFChars(reason, NULL);       __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,                LINUX_REBOOT_CMD_RESTART2, (char*) chars);       env->ReleaseStringUTFChars(reason, chars);  // In case it fails.    }    jniThrowIOException(env,errno);#endif}

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

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

四、sys_reboot的定义与实现


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

// kernel/kernel/sys.cSYSCALL_DEFINE4(reboot, int, magic1, int,magic2, unsigned int, cmd,                                void__user *, arg) //kernel/include/linux/syscalls.h#define __SYSCALL_DEFINEx(x, name, ...)                                                                  \                asmlinkagelong sys##name(__SC_DECL##x(__VA_ARGS__)) #define SYSCALL_DEFINEx(x, sname, ...)                                                     \                __SYSCALL_DEFINEx(x,sname, __VA_ARGS__) #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);

// kernel/kernel/sys.cvoid kernel_restart_prepare(char *cmd){                blocking_notifier_call_chain(&reboot_notifier_list,SYS_RESTART, cmd);                system_state= SYSTEM_RESTART;                device_shutdown();                sysdev_shutdown();}

//kernel/arch/arm/kernel/process.cvoid machine_restart(char *cmd){                arm_pm_restart(reboot_mode,cmd);}

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. Android(安卓)Service使用
  2. [学习记录]旋转屏幕禁止重新调用oncreat
  3. Android(安卓)FrameWork 之Binder机制初识
  4. [Android(安卓)Webkit]JNI基础及Java层与C++层的交互
  5. android 输入法框梳理
  6. android.app.Activity 的介绍(转)
  7. Android(安卓)SDK API 13升级指南
  8. Android(安卓)Adapter
  9. WebView的Java和javascript相互调用

随机推荐

  1. android 多媒体部分学习笔记十五-----视
  2. android 中生成XML文件的代码
  3. ListView.CHOICE_MODE_MULTIPLE
  4. android代码混淆及打包相关
  5. Android(安卓)获取SDCard上图片和视频的
  6. Android(安卓)Post图片和数据
  7. android 根据SD卡中图片路径读取并显示SD
  8. android 监听 USB 拔插广播消息
  9. Android(安卓)Activity的onCreate()函数
  10. 使用adb命令启动Android程序