當AB系統升級時,有兩種方式來呼叫updateengine,來實作升級,一種方法是直接執行shell命令,呼叫 update_engine_client,帶引數來實作升級,另一種方式是應用層直接呼叫UpdateEngine的applyPayload方法來升級,
update_engine_client 帶參升級
shell命令呼叫update_engine_client帶引數去升級,具體如下:
update_engine_client --payload=file:///sdcard/payload.bin --update --headers="FILE_HASH=qeebzpLK4f/FaDAVJ9ilCxnUC/TMO16S5QP39AjsYKc=
FILE_SIZE=445814087
METADATA_HASH=nn9V2c3dQ3yHwQQJW0R0Q+y+OQzWuJ5FZt4HxCiAry0=
METADATA_SIZE=58898"
后面帶了payload-file和 headers的引數,那我們來分析下update_engine_client 到底是如何來作業的,
int main(int argc, char** argv) {
//初始化UpdateEngineClientAndroid,然后執行
chromeos_update_engine::internal::UpdateEngineClientAndroid client(
argc, argv);
return client.Run();
}
class UpdateEngineClientAndroid : public brillo::Daemon {
....
UpdateEngineClientAndroid 是繼承brillo::Daemon的,這個類我們在啟動update_engine里分析過,執行其Run函式時,會先呼叫 onInit(), 那我們一起來看看onInit:
int UpdateEngineClientAndroid::OnInit() {
int ret = Daemon::OnInit();
if (ret != EX_OK)
return ret;
//對后續引數的資料型別,默認值,以及引數解釋
DEFINE_bool(update, false, "Start a new update, if no update in progress.");
DEFINE_string(payload,
"http://127.0.0.1:8080/payload",
"The URI to the update payload to use.");
DEFINE_int64(offset, 0,
"The offset in the payload where the CrAU update starts. "
"Used when --update is passed.");
DEFINE_int64(size, 0,
"The size of the CrAU part of the payload. If 0 is passed, it "
"will be autodetected. Used when --update is passed.");
DEFINE_string(headers,
"",
"A list of key-value pairs, one element of the list per line. "
"Used when --update is passed.");
DEFINE_bool(suspend, false, "Suspend an ongoing update and exit.");
DEFINE_bool(resume, false, "Resume a suspended update.");
DEFINE_bool(cancel, false, "Cancel the ongoing update and exit.");
DEFINE_bool(reset_status, false, "Reset an already applied update and exit.");
DEFINE_bool(follow,
false,
"Follow status update changes until a final state is reached. "
"Exit status is 0 if the update succeeded, and 1 otherwise.");
// 使用Brillo::FlagHelper來決議帶的引數
base::CommandLine::Init(argc_, argv_);
brillo::FlagHelper::Init(argc_, argv_, "Android Update Engine Client");
if (argc_ == 1) {
LOG(ERROR) << "Nothing to do. Run with --help for help.";
return 1;
}
// 檢測引數的合法性
const std::vector<std::string> positional_args =
base::CommandLine::ForCurrentProcess()->GetArgs();
if (!positional_args.empty()) {
LOG(ERROR) << "Found a positional argument '" << positional_args.front()
<< "'. If you want to pass a value to a flag, pass it as "
"--flag=value.";
return 1;
}
//啟動brillo的log系統
bool keep_running = false;
brillo::InitLog(brillo::kLogToStderr);
//啟動一個binder的看門狗
binder_watcher_.Init();
//通過Binder獲取UpdateEngineService的服務,并賦仠給service_
android::status_t status = android::getService(
android::String16("android.os.UpdateEngineService"), &service_);
if (status != android::OK) {
LOG(ERROR) << "Failed to get IUpdateEngine binder from service manager: "
<< Status::fromStatusT(status).toString8();
return ExitWhenIdle(1);
}
//如果有接suspend的引數
if (FLAGS_suspend) {
return ExitWhenIdle(service_->suspend());
}
//如果有接resume引數
if (FLAGS_resume) {
return ExitWhenIdle(service_->resume());
}
//如果有接cancel引數
if (FLAGS_cancel) {
return ExitWhenIdle(service_->cancel());
}
//如果有接reset_status引數
if (FLAGS_reset_status) {
return ExitWhenIdle(service_->resetStatus());
}
//如果有接follow,
if (FLAGS_follow) {
// Register a callback object with the service.
callback_ = new UECallback(this);
bool bound;
if (!service_->bind(callback_, &bound).isOk() || !bound) {
LOG(ERROR) << "Failed to bind() the UpdateEngine daemon.";
return 1;
}
keep_running = true;
}
//如果有接update引數,決議分割headers引數
if (FLAGS_update) {
std::vector<std::string> headers = base::SplitString(
FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::vector<android::String16> and_headers;
for (const auto& header : headers) {
and_headers.push_back(android::String16{header.data(), header.size()});
}
//執行applyPayload函式,執行升級
Status status = service_->applyPayload(
android::String16{FLAGS_payload.data(), FLAGS_payload.size()},
FLAGS_offset,
FLAGS_size,
and_headers);
if (!status.isOk())
return ExitWhenIdle(status);
}
if (!keep_running)
return ExitWhenIdle(EX_OK);
//監聽service_狀態的改變,如UpdateEngineServiceDied
android::BinderWrapper::Create();
android::BinderWrapper::Get()->RegisterForDeathNotifications(
android::os::IUpdateEngine::asBinder(service_),
base::Bind(&UpdateEngineClientAndroid::UpdateEngineServiceDied,
base::Unretained(this)));
return EX_OK;
}
從上面可以看到先定義引數的資料型別,檢查其合法,決議引數,獲取updateEngineService服務,然后執行其applyPayload,這個方式感覺UpdateEngine.applyPayload方式一樣,具體是否一致呢,我們來看看UpdateEngine的applyPayload的實作,
UpdateEngine.applyPayload
public void applyPayload(String url, long offset, long size, String[] headerKeyValuePairs) {
try {
//呼叫 service的applyPayload
mUpdateEngine.applyPayload(url, offset, size, headerKeyValuePairs);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public UpdateEngine() {
//mUpdateEngine 也是通過Binder獲取update_engine service
mUpdateEngine = IUpdateEngine.Stub.asInterface(
ServiceManager.getService(UPDATE_ENGINE_SERVICE));
}
那我們猜的結果是一樣,也是呼叫updateEngine服務的applyPayload,那升級的具體實作其實是呼叫applyPayload來實作的,
UpdateEngine服務
上面看到不管是update_engine_client 還是Java層的updateEngine介面,最后呼叫到都是updateEngine服務,對應到的是BinderUpdateEngineAndroidService:
class BinderUpdateEngineAndroidService : public android::os::BnUpdateEngine,
public ServiceObserverInterface {
const char* ServiceName() const {
return "android.os.UpdateEngineService";
}
}
Status BinderUpdateEngineAndroidService::applyPayload(
const android::String16& url,
int64_t payload_offset,
int64_t payload_size,
const std::vector<android::String16>& header_kv_pairs) {
const std::string payload_url{android::String8{url}.string()};
std::vector<std::string> str_headers;
str_headers.reserve(header_kv_pairs.size());
for (const auto& header : header_kv_pairs) {
str_headers.emplace_back(android::String8{header}.string());
}
brillo::ErrorPtr error;
if (!service_delegate_->ApplyPayload(
payload_url, payload_offset, payload_size, str_headers, &error)) {
return ErrorPtrToStatus(error);
}
return Status::ok();
}
updateService 實際上的是service_delegate_,這個也是DaemonStateAndroid 獲取的service_delegate,也就是update_attempter_.get(), 對應的類是UpdateAttempterAndroid,
bool UpdateAttempterAndroid::ApplyPayload(
const string& payload_url,
int64_t payload_offset,
int64_t payload_size,
const vector<string>& key_value_pair_headers,
brillo::ErrorPtr* error) {
//如果需要升級,不能繼續再升級了
if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
return LogAndSetError(
error, FROM_HERE, "An update already applied, waiting for reboot");
}
//如果在升級程序中,不能繼續升級
if (ongoing_update_) {
return LogAndSetError(
error, FROM_HERE, "Already processing an update, cancel it first.");
}
DCHECK(status_ == UpdateStatus::IDLE);
//將headers的引數決議出來后,添加到headers的maps中
std::map<string, string> headers;
for (const string& key_value_pair : key_value_pair_headers) {
string key;
string value;
if (!brillo::string_utils::SplitAtFirst(
key_value_pair, "=", &key, &value, false)) {
return LogAndSetError(
error, FROM_HERE, "Passed invalid header: " + key_value_pair);
}
if (!headers.emplace(key, value).second)
return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key);
}
//設定一個對應的獨一無二的id
string payload_id = (headers[kPayloadPropertyFileHash] +
headers[kPayloadPropertyMetadataHash]);
//初始化一個install_plan_, 然后將applyPayload的引數賦值給install_plan_,
install_plan_ = InstallPlan();
install_plan_.download_url = payload_url;
install_plan_.version = "";
base_offset_ = payload_offset;
InstallPlan::Payload payload;
payload.size = payload_size;
if (!payload.size) {
if (!base::StringToUint64(headers[kPayloadPropertyFileSize],
&payload.size)) {
payload.size = 0;
}
}
if (!brillo::data_encoding::Base64Decode(headers[kPayloadPropertyFileHash],
&payload.hash)) {
LOG(WARNING) << "Unable to decode base64 file hash: "
<< headers[kPayloadPropertyFileHash];
}
if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize],
&payload.metadata_size)) {
payload.metadata_size = 0;
}
// The |payload.type| is not used anymore since minor_version 3.
payload.type = InstallPayloadType::kUnknown;
install_plan_.payloads.push_back(payload);
// The |public_key_rsa| key would override the public key stored on disk.
install_plan_.public_key_rsa = "";
install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
install_plan_.is_resume = !payload_id.empty() &&
DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
if (!install_plan_.is_resume) {
if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
LOG(WARNING) << "Unable to reset the update progress.";
}
if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
LOG(WARNING) << "Unable to save the update check response hash.";
}
}
install_plan_.source_slot = boot_control_->GetCurrentSlot();
install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
install_plan_.powerwash_required =
GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false);
install_plan_.switch_slot_on_reboot =
GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true);
install_plan_.run_post_install = true;
//判斷是否可以設定run_post_install
if (install_plan_.is_resume && prefs_->Exists(kPrefsPostInstallSucceeded)) {
bool post_install_succeeded = false;
prefs_->GetBoolean(kPrefsPostInstallSucceeded, &post_install_succeeded);
if (post_install_succeeded) {
install_plan_.run_post_install =
GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
}
}
//檢測網路id
NetworkId network_id = kDefaultNetworkId;
if (!headers[kPayloadPropertyNetworkId].empty()) {
if (!base::StringToUint64(headers[kPayloadPropertyNetworkId],
&network_id)) {
return LogAndSetError(
error,
FROM_HERE,
"Invalid network_id: " + headers[kPayloadPropertyNetworkId]);
}
if (!network_selector_->SetProcessNetwork(network_id)) {
return LogAndSetError(
error,
FROM_HERE,
"Unable to set network_id: " + headers[kPayloadPropertyNetworkId]);
}
}
//列印install_plan_的資訊
LOG(INFO) << "Using this install plan:";
install_plan_.Dump();
//開啟UpdateAction的動作,開啟推動升級開始
BuildUpdateActions(payload_url);
//設定額外的校驗頭 和 用戶代理的頭
HttpFetcher* fetcher = download_action_->http_fetcher();
if (!headers[kPayloadPropertyAuthorization].empty())
fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]);
if (!headers[kPayloadPropertyUserAgent].empty())
fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
//回呼升級的狀態
SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
ongoing_update_ = true;
//升級之前,確認當前的bootFlags 已經 更新
UpdateBootFlags();
//更新本地存盤的升級資訊,包括 ,升級次數,重啟次數,升級時間等
UpdatePrefsOnUpdateStart(install_plan_.is_resume);
return true;
}
從上面的注釋里可以看到,先將applyPayload的相關資訊與引數傳給install_plan_的結構體中,然后呼叫BuildUpdateActions去開啟升級,那下面我們繼續分析BuildUpdateActions(payload_url),
void UpdateAttempterAndroid::BuildUpdateActions(const string& url) {
CHECK(!processor_->IsRunning());
processor_->set_delegate(this);
//初始化InstallPlanAction的升級安裝行動
shared_ptr<InstallPlanAction> install_plan_action(
new InstallPlanAction(install_plan_));
HttpFetcher* download_fetcher = nullptr;
if (FileFetcher::SupportedUrl(url)) {
DLOG(INFO) << "Using FileFetcher for file URL.";
download_fetcher = new FileFetcher();
} else {
#ifdef _UE_SIDELOAD
LOG(FATAL) << "Unsupported sideload URI: " << url;
#else
LibcurlHttpFetcher* libcurl_fetcher =
new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
download_fetcher = libcurl_fetcher;
#endif // _UE_SIDELOAD
}
//初始化DownloadAction的下載行為
shared_ptr<DownloadAction> download_action(
new DownloadAction(prefs_,
boot_control_,
hardware_,
nullptr, // system_state, not used.
download_fetcher, // passes ownership
true /* is_interactive */));
//初始化FilesystemVerifierAction的檔案系統校驗行為
shared_ptr<FilesystemVerifierAction> filesystem_verifier_action(
new FilesystemVerifierAction());
//初始化PostinstallRunnerAction 推動安裝運行行為
shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
new PostinstallRunnerAction(boot_control_, hardware_));
download_action->set_delegate(this);
download_action->set_base_offset(base_offset_);
download_action_ = download_action;
postinstall_runner_action->set_delegate(this);
//將上面的四種不同的行為添加到actions_的串列中,
actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
actions_.push_back(shared_ptr<AbstractAction>(download_action));
actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action));
actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
// 將相互連接的兩種行為按順序的系結在一起
BondActions(install_plan_action.get(), download_action.get());
BondActions(download_action.get(), filesystem_verifier_action.get());
BondActions(filesystem_verifier_action.get(),
postinstall_runner_action.get());
//將actions串列加入到processor_的作業佇列中去,以推動這些行為開始作業起來,
for (const shared_ptr<AbstractAction>& action : actions_)
processor_->EnqueueAction(action.get());
}
BuildUpdateActions()函式主要作業1. 初始化各種Actions 2. 將這些Action加入到Actions_佇列中, 然后系結他們運行順序,3. 將Actions串列中的action 添加到processor_的作業佇列中去,
下一篇我們就看processor_的作業佇列在如何運行,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/287626.html
標籤:其他
上一篇:安卓的相對布局與線性布局
