really_install_package()函数
really_install_package()函数位于install.cpp。
static int really_install_package(const std::string &path, bool *wipe_cache, bool needs_mount,
std::vector<std::string> *log_buffer, int retry_count,
int *max_temperature) {
// Timothy:这部分跟UI相关
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
ui->Print("Finding update package...\n");
// Give verification half the progress bar...
ui->SetProgressType(RecoveryUI::DETERMINATE);
ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
LOG(INFO) << "Update location: " << path;
// Map the update package into memory.
ui->Print("Opening update package...\n");
if (needs_mount) {
if (path[0] == '@') {
ensure_path_mounted(path.substr(1).c_str());
} else {
ensure_path_mounted(path.c_str());
}
}
MemMapping map;
if (!map.MapFile(path)) {
LOG(ERROR) << "failed to map file";
return INSTALL_CORRUPT;
}
// Timothy:对安装包进行验证,粗看应该是验证签名,具体的后面再分析。
// Verify package.
if (!verify_package(map.addr, map.length)) {
log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
return INSTALL_CORRUPT;
}
// Try to open the package.
ZipArchiveHandle zip;
int err = OpenArchiveFromMemory(map.addr, map.length, path.c_str(), &zip);
if (err != 0) {
LOG(ERROR) << "Can't open " << path << " : " << ErrorCodeString(err);
log_buffer->push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
CloseArchive(zip);
return INSTALL_CORRUPT;
}
// Timothy:AB_OTA_UPDATER应该控制做AB升级的,这里没有定义。
// Check partition size between source and target
#ifndef AB_OTA_UPDATER
int ret = INSTALL_SUCCESS;
if (mt_really_install_package_check_part_size(ret, path.c_str(), needs_mount, zip)) {
CloseArchive(zip);
return ret;
}
#endif
// Timothy:这里的验证是验证ota包中的一个包含兼容性信息的zip文件。从日志看,我们的ota包里面不含
// 这个zip文件,所以直接返回了true。
// Additionally verify the compatibility of the package.
if (!verify_package_compatibility(zip)) {
log_buffer->push_back(android::base::StringPrintf("error: %d", kPackageCompatibilityFailure));
CloseArchive(zip);
return INSTALL_CORRUPT;
}
// Verify and install the contents of the package.
ui->Print("Installing update...\n");
if (retry_count > 0) {
ui->Print("Retry attempt: %d\n", retry_count);
}
// Timothy:这里实际上是设置了一个UI用的全局变量,这个变量为false时,不能有软件控制的重启。
ui->SetEnableReboot(false);
// Timothy:这里释放二进制文件并运行它。
int result = try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature);
ui->SetEnableReboot(true);
ui->Print("\n");
CloseArchive(zip);
return result;
}
try_update_binary()函数
try_update_binary()函数位于install.cpp。
static int try_update_binary(const std::string &package, ZipArchiveHandle zip, bool *wipe_cache,
std::vector<std::string> *log_buffer, int retry_count,
int *max_temperature) {
// Timothy:从ota升级包中读取build.version.incremental并打印到日志。这个应该是只有增量包升级的时候才有。
read_source_target_build(zip, log_buffer);
// Timothy:初始化管道,用于主进程和安装进程通信。主进程用于更新UI,子进程是实际干活的进程。
int pipefd[2];
pipe(pipefd);
std::vector<std::string> args;
// Timothy:因为宏AB_OTA_UPDATER没有有定义,所以走了第二个分支。
#ifdef AB_OTA_UPDATER
// Timothy:这里从升级包里面释放META-INF/com/google/android/update-binary这个二进制文件,
// 然后把信息存储在args里面。
int ret = update_binary_command(package, zip, "/sbin/update_engine_sideload", retry_count,
pipefd[1], &args);
#else
int ret = update_binary_command(package, zip, "/tmp/update-binary", retry_count, pipefd[1],
&args);
#endif
if (ret) {
close(pipefd[0]);
close(pipefd[1]);
return ret;
}
// When executing the update binary contained in the package, the
// arguments passed are:
//
// - the version number for this interface
//
// - an FD to which the program can write in order to update the
// progress bar. The program can write single-line commands:
//
// progress <frac> <secs>
// fill up the next <frac> part of of the progress bar
// over <secs> seconds. If <secs> is zero, use
// set_progress commands to manually control the
// progress of this segment of the bar.
//
// set_progress <frac>
// <frac> should be between 0.0 and 1.0; sets the
// progress bar within the segment defined by the most
// recent progress command.
//
// ui_print <string>
// display <string> on the screen.
//
// wipe_cache
// a wipe of cache will be performed following a successful
// installation.
//
// clear_display
// turn off the text display.
//
// enable_reboot
// packages can explicitly request that they want the user
// to be able to reboot during installation (useful for
// debugging packages that don't exit).
//
// retry_update
// updater encounters some issue during the update. It requests
// a reboot to retry the same package automatically.
//
// log <string>
// updater requests logging the string (e.g. cause of the
// failure).
//
// - the name of the package zip file.
//
// - an optional argument "retry" if this update is a retry of a failed
// update attempt.
//
// Timothy:将前面得到的二进制文件转换成execv可以执行的字符串。
// Convert the vector to a NULL-terminated char* array suitable for execv.
const char *chr_args[args.size() + 1];
chr_args[args.size()] = nullptr;
for (size_t i = 0; i < args.size(); i++) {
chr_args[i] = args[i].c_str();
}
pid_t pid = fork();
if (pid == -1) {
close(pipefd[0]);
close(pipefd[1]);
PLOG(ERROR) << "Failed to fork update binary";
return INSTALL_ERROR;
}
// Timothy:子进程里面执行chr_args里面存储的命令
if (pid == 0) {
umask(022);
close(pipefd[0]);
execv(chr_args[0], const_cast<char **>(chr_args));
// Bug: 34769056
// We shouldn't use LOG/PLOG in the forked process, since they may cause
// the child process to hang. This deadlock results from an improperly
// copied mutex in the ui functions.
fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
_exit(EXIT_FAILURE);
}
close(pipefd[1]);
std::atomic<bool> logger_finished(false);
std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));
*wipe_cache = false;
bool retry_update = false;
// Timothy:根据子进程从通道里面传过来的值,进行不同的显示。
char buffer[1024];
FILE *from_child = fdopen(pipefd[0], "r");
while (fgets(buffer, sizeof(buffer), from_child) != nullptr) {
std::string line(buffer);
size_t space = line.find_first_of(" \n");
std::string command(line.substr(0, space));
if (command.empty()) continue;
// Get rid of the leading and trailing space and/or newline.
std::string args = space == std::string::npos ? "" : android::base::Trim(line.substr(space));
if (command == "progress") {
std::vector<std::string> tokens = android::base::Split(args, " ");
double fraction;
int seconds;
if (tokens.size() == 2 && android::base::ParseDouble(tokens[0].c_str(), &fraction) &&
android::base::ParseInt(tokens[1], &seconds)) {
ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds);
} else {
LOG(ERROR) << "invalid \"progress\" parameters: " << line;
}
} else if (command == "set_progress") {
std::vector<std::string> tokens = android::base::Split(args, " ");
double fraction;
if (tokens.size() == 1 && android::base::ParseDouble(tokens[0].c_str(), &fraction)) {
ui->SetProgress(fraction);
} else {
LOG(ERROR) << "invalid \"set_progress\" parameters: " << line;
}
} else if (command == "ui_print") {
ui->PrintOnScreenOnly("%s\n", args.c_str());
fflush(stdout);
} else if (command == "wipe_cache") {
*wipe_cache = true;
} else if (command == "clear_display") {
ui->SetBackground(RecoveryUI::NONE);
} else if (command == "enable_reboot") {
// packages can explicitly request that they want the user
// to be able to reboot during installation (useful for
// debugging packages that don't exit).
ui->SetEnableReboot(true);
} else if (command == "retry_update") {
retry_update = true;
} else if (command == "log") {
if (!args.empty()) {
// Save the logging request from updater and write to last_install later.
log_buffer->push_back(args);
} else {
LOG(ERROR) << "invalid \"log\" parameters: " << line;
}
} else {
LOG(ERROR) << "unknown command [" << command << "]";
}
}
fclose(from_child);
int status;
waitpid(pid, &status, 0);
logger_finished.store(true);
finish_log_temperature.notify_one();
temperature_logger.join();
if (retry_update) {
return INSTALL_RETRY;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
LOG(ERROR) << "Error in " << package << " (Status " << WEXITSTATUS(status) << ")";
return INSTALL_ERROR;
}
return INSTALL_SUCCESS;
}
update_binary_command()函数
update_binary_command()函数位于install.cpp。
int update_binary_command(const std::string &package, ZipArchiveHandle zip,
const std::string &binary_path, int retry_count, int status_fd,
std::vector<std::string> *cmd) {
CHECK(cmd != nullptr);
// Timothy:从zip包中解压下面的升级文件
// On traditional updates we extract the update binary from the package.
static constexpr const char *UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
ZipString binary_name(UPDATE_BINARY_NAME);
ZipEntry binary_entry;
if (FindEntry(zip, binary_name, &binary_entry) != 0) {
LOG(ERROR) << "Failed to find update binary " << UPDATE_BINARY_NAME;
return INSTALL_CORRUPT;
}
unlink(binary_path.c_str());
int fd = open(binary_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0755);
if (fd == -1) {
PLOG(ERROR) << "Failed to create " << binary_path;
return INSTALL_ERROR;
}
int32_t error = ExtractEntryToFile(zip, &binary_entry, fd);
close(fd);
if (error != 0) {
LOG(ERROR) << "Failed to extract " << UPDATE_BINARY_NAME << ": " << ErrorCodeString(error);
return INSTALL_ERROR;
}
// Timothy:拼接升级命令。这个就是前面提到的子线程执行execv执行的命令。
*cmd = {
binary_path,
EXPAND(RECOVERY_API_VERSION), // defined in Android.mk
std::to_string(status_fd),
package,
};
if (retry_count > 0) {
cmd->push_back("retry");
}
return 0;
}