Android OTA upgrade (2): start the upgrade process

Tian Haili@CSDN

2013-3-31

 

After the OTA upgrade package is obtained through the network or directly locally, the Android upgrade can be started through the program. This article describes this process.

 

After obtaining the OTA upgrade package, you can directly start the OTA upgrade through android.os.RecoverySystem.installPackage().

RecoverySystem.installPackage() was added after API-8. To use it, permission is required: android.Manifest.permission.REBOOT

 

One, the realization of RecoverySystem#installPackage()

 

RecoverySystem.installPackage() is to pass the file name of the incoming file through arg "--update_package=<filename>" [<filename> is replaced by a specific file] and call bootCommand() to achieve.

 

Implementation of 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 is "/cache/recovery/command". bootCommand() is to write "--update_package=<filename>" to /cache/recovery/command, then call reboot() of PowerManagerService through BinderIPC, and pass "recovery" as a parameter.

 

Second, the realization of PowerManagerService#reboot


PowerManagerService.reboot(reason: String) is realized by starting the execution of ShutdownThread.reboot(mContext, finalReason, false).

 

The execution sequence diagram is shown in the figure, and the values ​​are:

- reason: “recovery”;

- confirm: false;

-The parameters of rebootOrShutdown have values: reboot <- mReboot; reason<- mRebootReason;

Finally, Power.reboot() is called, and its c implementation is called through JNI.

 

The JNI implementation in Power.java is in android_os_power.cpp.


3. Native implementation of Power.reboot


Power.reboot() is implemented through 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
}

The system calls __reboot and embeds the kernel to realize reboot.

 

In the kernel mode, enter the sys_reboot system definition.

 

Fourth, the definition and implementation of sys_reboot


The definition and implementation of sys_reboot depends on the code in the kernel 

// kernel/kernel/sys.c
SYSCALL_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__)

Therefore, SYSCALL_DEFINE4(reboot, ...) in sys.c implements sys_reboot()

 

SYSCALL_DEFINE4(reboot,...) discriminates between magic1 and magic2 . Only the matching magic1 and magic2 will be processed, otherwise it will return directly.

For cmd LINUX_REBOOT_CMD_RESTART2 : Copy the reboot reason from user mode to kernel mode, and call kernel_restart() to execute.

 

kernel_restart(char* cmd) first call kernel_restart_prepare(cmd); then call machine_restart(cmd); 

// kernel/kernel/sys.c
void 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.c
void machine_restart(char *cmd)
{
                arm_pm_restart(reboot_mode,cmd);
}

arm_pm_restart points to the function pointer of the machine restart defined by the specific platform. The prototype is void(*arm_pm_restart)(char str, const char *cmd).

The specific implementation is related to the specific platform used, and will not be described here.

 

to sum up


This article describes the process of initiating OTA upgrade in Android, from Framework to JNI, and then to the Kernel layer. The analysis of the layer-by-layer relationship shows that the so-called OTA upgrade is initiated by putting "-" in /cache/recovery/command. -update_package=<filename>” is written, and then transferred to the kernel mode to execute the system call through the system call to realize the machine restart and complete the whole process of OTA upgrade.

After restarting, the process of entering Recovery mode will be discussed in a later topic.

 

Guess you like

Origin blog.csdn.net/thl789/article/details/8743768