田海立@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,...)中對magic1和magic2進行判別,只有符合的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模式的過程在後面的專題中再討論。