上篇已经分析过了InstallPlanAction、DownloadAction、FileSystemVerityAction 三个Action的工作内容,还有一个PostinstallRunnerAction的在这篇中继续分析,每个Action都是从PerformAction开始的:
void PostinstallRunnerAction::PerformAction() {
CHECK(HasInputObject());
install_plan_ = GetInputObject();
if (install_plan_.powerwash_required) {
if (hardware_->SchedulePowerwash()) {
powerwash_scheduled_ = true;
} else {
return CompletePostinstall(ErrorCode::kPostinstallPowerwashError);
}
}
partition_weight_.resize(install_plan_.partitions.size());
total_weight_ = 0;
for (size_t i = 0; i < install_plan_.partitions.size(); ++i) {
partition_weight_[i] = install_plan_.partitions[i].run_postinstall;
total_weight_ += partition_weight_[i];
}
accumulated_weight_ = 0;
ReportProgress(0);
PerformPartitionPostinstall();
}
上面主要做判断是否需要powerwash_,一般的升级方式不需要powerwash,然后初始升级分区的权重,同时保存这些权重值,之后开始分区升级:
void PostinstallRunnerAction::PerformPartitionPostinstall() {
if (!install_plan_.run_post_install) {
LOG(INFO) << "Skipping post-install according to install plan.";
return CompletePostinstall(ErrorCode::kSuccess);
}
if (install_plan_.download_url.empty()) {
LOG(INFO) << "Skipping post-install during rollback";
return CompletePostinstall(ErrorCode::kSuccess);
}
while (current_partition_ < install_plan_.partitions.size() &&
!install_plan_.partitions[current_partition_].run_postinstall) {
VLOG(1) << "Skipping post-install on partition "
<< install_plan_.partitions[current_partition_].name;
current_partition_++;
}
if (current_partition_ == install_plan_.partitions.size())
return CompletePostinstall(ErrorCode::kSuccess);
const InstallPlan::Partition& partition =
install_plan_.partitions[current_partition_];
const string mountable_device =
utils::MakePartitionNameForMount(partition.target_path);
if (mountable_device.empty()) {
LOG(ERROR) << "Cannot make mountable device from " << partition.target_path;
return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
}
#ifdef __ANDROID__
fs_mount_dir_ = "/postinstall";
#else
base::FilePath temp_dir;
TEST_AND_RETURN(base::CreateNewTempDirectory("au_postint_mount", &temp_dir));
fs_mount_dir_ = temp_dir.value();
#endif
if (utils::IsMountpoint(fs_mount_dir_)) {
LOG(INFO) << "Found previously mounted filesystem at " << fs_mount_dir_;
utils::UnmountFilesystem(fs_mount_dir_);
}
base::FilePath postinstall_path(partition.postinstall_path);
if (postinstall_path.IsAbsolute()) {
LOG(ERROR) << "Invalid absolute path passed to postinstall, use a relative"
"path instead: "
<< partition.postinstall_path;
return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
}
string abs_path =
base::FilePath(fs_mount_dir_).Append(postinstall_path).value();
if (!base::StartsWith(
abs_path, fs_mount_dir_, base::CompareCase::SENSITIVE)) {
LOG(ERROR) << "Invalid relative postinstall path: "
<< partition.postinstall_path;
return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
}
#ifdef __ANDROID__
if (!utils::SetBlockDeviceReadOnly(mountable_device, true)) {
return CompletePartitionPostinstall(
1, "Error marking the device " + mountable_device + " read only.");
}
#endif
if (!utils::MountFilesystem(mountable_device,
fs_mount_dir_,
MS_RDONLY,
partition.filesystem_type,
constants::kPostinstallMountOptions)) {
return CompletePartitionPostinstall(
1, "Error mounting the device " + mountable_device);
}
LOG(INFO) << "Performing postinst (" << partition.postinstall_path << " at "
<< abs_path << ") installed on device " << partition.target_path
<< " and mountable device " << mountable_device;
LOG(INFO) << "Format file for new " << partition.postinstall_path
<< " is: " << utils::GetFileFormat(abs_path);
vector<string> command = {abs_path};
#ifdef __ANDROID__
command.push_back(std::to_string(install_plan_.target_slot));
command.push_back(std::to_string(kPostinstallStatusFd));
#else
command.push_back(partition.target_path);
#endif
current_command_ = Subprocess::Get().ExecFlags(
command,
Subprocess::kRedirectStderrToStdout,
{kPostinstallStatusFd},
base::Bind(&PostinstallRunnerAction::CompletePartitionPostinstall,
base::Unretained(this)));
CHECK_GE(current_command_, 0);
if (!current_command_) {
CompletePartitionPostinstall(1, "Postinstall didn't launch");
return;
}
progress_fd_ =
Subprocess::Get().GetPipeFd(current_command_, kPostinstallStatusFd);
int fd_flags = fcntl(progress_fd_, F_GETFL, 0) | O_NONBLOCK;
if (HANDLE_EINTR(fcntl(progress_fd_, F_SETFL, fd_flags)) < 0) {
PLOG(ERROR) << "Unable to set non-blocking I/O mode on fd " << progress_fd_;
}
progress_task_ = MessageLoop::current()->WatchFileDescriptor(
FROM_HERE,
progress_fd_,
MessageLoop::WatchMode::kWatchRead,
true,
base::Bind(&PostinstallRunnerAction::OnProgressFdReady,
base::Unretained(this)));
}
上面执行partition.postinstall_path的指令,然后从执行的过程中,获取状态和进度,但从生成的update.zip包看查看,没有postinstall_path这个执行脚本。所以这一步在android升级中是没有做任何事情的。 下篇我们将重点的研究DownloadAction 里的工作和下载的流程,AB升级的实际分区升级的工作也是在这个里面进行的。
|