[System] android android system upgrade analysis process (a) for the upgrade process update packet mode --- Recovery Analysis

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/twk121109281/article/details/90748513

Today, we are in direct android specific upgrade procedure is a look at how.


Upgrade Process Overview

Flowchart upgrade:

Upgrade Process Analysis

The first step: get upgrade package

Get upgrade via remote download or copy directly to the specified directory.

Step 2: Prepare to upgrade

Then call RecoverySystem.installPackage passed down through the directory parameter passing mode. This is the application layer code is as follows:

public void updateSystem(String updateSavePath) {
    File packageFile = new File(updateSavePath);
    try {
        //调用升级接口
        RecoverySystem.installPackage(this, packageFile);
    } catch (IOException e) {
        LOG.e(TAG, "RecoverySystem ERROR!!!");
        e.printStackTrace();
        String errDesc =String.format("execute system update fail. reason-> %s", e.toString());
        reportUpdateError(errDesc);
    }

    LOG.d(TAG, "RecoverySystem OK!!!");
    copyUpdateFileIsSuccess = false;
}

After the application layer download the upgrade package, calls RecoverySystem.installPackage (Context context, File packageFile) function to initiate the installation process, the main principle of this process, in fact, just to / cache / recovery / command writes upgrade package storage path, then reboot to recovery mode, and nothing more.

public static void installPackage(Context context, File packageFile)
    throws IOException {
    String filename = packageFile.getCanonicalPath();
    Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");

    //升级包路径
    final String filenameArg = "--update_package=" + filename;
    final String localeArg = "--locale=" + Locale.getDefault().toString();
    bootCommand(context, filenameArg, localeArg);
}

private static void bootCommand(Context context, String... args) throws IOException {
    RECOVERY_DIR.mkdirs();  // In case we need it
    COMMAND_FILE.delete();  // In case it's not writable
    LOG_FILE.delete();
    FileWriter command = new FileWriter(COMMAND_FILE);
    try {
        for (String arg : args) {
            if (!TextUtils.isEmpty(arg)) {
                command.write(arg);
                command.write("\n");
            }
        }
    } finally {
        command.close();
    }
    // Having written the command file, go ahead and reboot
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    //重启到recovery模式
    pm.reboot(PowerManager.REBOOT_RECOVERY);
    throw new IOException("Reboot failed (no permissions?)");
}

PowerManager.REBOOT_RECOVERY contains the string "recovery", pm.reboot () method of recovery will be written to the last BCB misc partition to. BCB i.e. Bootloader Control Block, the startup control block, partition misc located, viewed from the code, is a structured body. as follows:

struct bootloader_message {  
    char command[32];  
    char status[32];  
    char recovery[1024];  
}; 

bootloader_message structure comprises three fields, in particular the following meanings:

command is a command stored in the field, it has the following possible values: 
* Boot-Recovery: The system will start Recovery Mode 
* update-radia or update-hboot: The system will start to enter the firmware update mode, the update process by the bootloader complete 
* NULL: null value, the system will boot into main system main system starts normally.

status storage field is updated results. After the update, the update result Bootloader Recovery or written to this field.

recovery field is stored in the boot parameters recovry module, generally including upgrade package path. Storing structured as follows: The first line stored character string "recovery", the second line storage path information "-update_package = / mnt / sdcard / update.zip" and the like. Therefore, the argument is between "\ n" segmentation.

The third step: the system restarts Recovery mode, upgrade

 When the Android system upgrade, there are two ways:

One is through the interface transmission path automatically upgraded upgrade package (Android system upgrade SD card), complete system automatically restart after the upgrade.

Another is to manually enter the recovery mode, select upgrade package to upgrade, the upgrade is complete after the stay in the recovery interface, need to manually select to restart.

The former client for mobile phone manufacturers to upgrade the end-line, which is used for development and testing staff. But no matter what, the principles are the same, are upgraded in recovery mode.

Here upgrade package is stored in the cache directory, and the update package stored in the path / cache / recovery / command in a manner (storage path upgrade package, or from BCB / cache / recovery / command parsed inside).

Reboot into major upgrade process:

  1. System reboot into Recovery mode. After reading the command BCB, read "boot-recovery", loaded recovery.img, start recovery.
  2. In install.cpp to upgrade the
  3. try_update_binary perform the upgrade script
  4. Call finish_recovery method, BCB clear information, restart

1, the system reboot into Recovery mode

    It will determine whether there is command files / cache / recovery directory when the system reboots, if there is to enter recovery mode, otherwise it starts normally.

    Into Recovery mode, the main function performed recovery.cpp, put the key code fragment below:

... ...
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {  
    switch (arg) {  
    case 's': send_intent = optarg; break;  
    case 'u': update_package = optarg; break;  
    ... ... 
} 
... ...

2, the install.cpp to upgrade the

In the main function will eventually call to install_package method.

... ...
if (update_package != NULL) {  
    status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE, true);  
    ... ...
} 
    ... ...

Specific upgrade procedure is performed in install.cpp, a look at install_package method.

int install_package(const char* path, int* wipe_cache, const char* install_file,  
                bool needs_mount)  
{  
    ... ...
    if (setup_install_mounts() != 0) {  
        ... ...
    } else {  
        result = really_install_package(path, wipe_cache, needs_mount);  
    }
    ... ...
}  

install_package method creates a log file (logging upgrade information being given). Then call really_install_package method.

static int really_install_package(const char *path, int* wipe_cache, bool needs_mount)  
{  
    ... ...
    // 装入签名文件
    Certificate* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
    ... ...
    // 验证签名
    err = verify_file(map.addr, map.length, loadedKeys, numKeys);
    ... ...
    // 打开升级包  
    err = mzOpenZipArchive(map.addr, map.length, &zip);
    ... ... 
    // 执行升级脚本文件,开始升级  
    int result = try_update_binary(path, &zip, wipe_cache);
    ... ...
}  

really_install_package method, first verify the signature, and then read the upgrade package, and then call the method to upgrade try_update_binary

3, try_update_binary perform the upgrade script

static int try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {

    const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    ... ...
    const char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755); 
    ... ...
    //将升级包里面的update_binary解压到/tmp/update_binary
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    ... ...

    const char** args = (const char**)malloc(sizeof(char*) * 5);
    args[0] = binary; //update_binary存放路径
    args[1] = EXPAND(RECOVERY_API_VERSION);  // Recovery版本号
    char* temp = (char*)malloc(10);
    sprintf(temp, "%d", pipefd[1]);
    args[2] = temp;
    args[3] = (char*)path; //升级包存放路径
    args[4] = NULL;

    pid_t pid = fork();//fork一个子进程
    if (pid == 0) {
        close(pipefd[0]);
        //子进程调用update-binary执行升级操作
        execv(binary, (char* const*)args);
        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
        _exit(-1);
    }
    //父进程负责接受子进程发送的命令去更新ui显示 
    ... ...
    int status;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        //安装失败,返回INSTALL_ERROR
        return INSTALL_ERROR;
    }
     //安装成功,返回INSTALL_SUCCESS
    return INSTALL_SUCCESS;
}

4, call finish_recovery method, BCB clear information, restart

OTA upgrade was successful, misc empty partition (BCB zero), and save the upgrade log is saved to memory system /tmp/recovery.log / cache / recovery / last_log. Reboot the device into the Main System, the upgrade is complete.

Conclusion

These are the upgrade process analysis, we want to help. We will also introduce the follow-up to bring the system upgrade process-related, interested students can focus our micro-channel public number.

å¨è¿éæå¥å¾çæè¿°

Previous: Contents

Next: [system] android android system upgrade process analysis (two) --- update packet analysis

Guess you like

Origin blog.csdn.net/twk121109281/article/details/90748513