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:
- System reboot into Recovery mode. After reading the command BCB, read "boot-recovery", loaded recovery.img, start recovery.
- In install.cpp to upgrade the
- try_update_binary perform the upgrade script
- 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