update_attempter_android.cc revision 0ee98439a9f4fa1ff7a97050147d49528c99a9b3
1// 2// Copyright (C) 2016 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "update_engine/update_attempter_android.h" 18 19#include <algorithm> 20#include <map> 21#include <utility> 22 23#include <base/bind.h> 24#include <base/logging.h> 25#include <base/strings/string_number_conversions.h> 26#include <brillo/bind_lambda.h> 27#include <brillo/message_loops/message_loop.h> 28#include <brillo/strings/string_utils.h> 29 30#include "update_engine/common/constants.h" 31#include "update_engine/common/libcurl_http_fetcher.h" 32#include "update_engine/common/multi_range_http_fetcher.h" 33#include "update_engine/common/utils.h" 34#include "update_engine/daemon_state_android.h" 35#include "update_engine/payload_consumer/download_action.h" 36#include "update_engine/payload_consumer/filesystem_verifier_action.h" 37#include "update_engine/payload_consumer/postinstall_runner_action.h" 38#include "update_engine/update_status_utils.h" 39 40using base::Bind; 41using base::TimeDelta; 42using base::TimeTicks; 43using std::shared_ptr; 44using std::string; 45using std::vector; 46 47namespace chromeos_update_engine { 48 49namespace { 50 51// Minimum threshold to broadcast an status update in progress and time. 52const double kBroadcastThresholdProgress = 0.01; // 1% 53const int kBroadcastThresholdSeconds = 10; 54 55const char* const kErrorDomain = "update_engine"; 56// TODO(deymo): Convert the different errors to a numeric value to report them 57// back on the service error. 58const char* const kGenericError = "generic_error"; 59 60// Log and set the error on the passed ErrorPtr. 61bool LogAndSetError(brillo::ErrorPtr* error, 62 const tracked_objects::Location& location, 63 const string& reason) { 64 brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason); 65 LOG(ERROR) << "Replying with failure: " << location.ToString() << ": " 66 << reason; 67 return false; 68} 69 70} // namespace 71 72UpdateAttempterAndroid::UpdateAttempterAndroid( 73 DaemonStateAndroid* daemon_state, 74 PrefsInterface* prefs, 75 BootControlInterface* boot_control, 76 HardwareInterface* hardware) 77 : daemon_state_(daemon_state), 78 prefs_(prefs), 79 boot_control_(boot_control), 80 hardware_(hardware), 81 processor_(new ActionProcessor()) { 82} 83 84UpdateAttempterAndroid::~UpdateAttempterAndroid() { 85 // Release ourselves as the ActionProcessor's delegate to prevent 86 // re-scheduling the updates due to the processing stopped. 87 processor_->set_delegate(nullptr); 88} 89 90void UpdateAttempterAndroid::Init() { 91 // In case of update_engine restart without a reboot we need to restore the 92 // reboot needed state. 93 if (UpdateCompletedOnThisBoot()) 94 SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT); 95 else 96 SetStatusAndNotify(UpdateStatus::IDLE); 97} 98 99bool UpdateAttempterAndroid::ApplyPayload( 100 const string& payload_url, 101 int64_t payload_offset, 102 int64_t payload_size, 103 const vector<string>& key_value_pair_headers, 104 brillo::ErrorPtr* error) { 105 if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) { 106 return LogAndSetError( 107 error, FROM_HERE, "An update already applied, waiting for reboot"); 108 } 109 if (ongoing_update_) { 110 return LogAndSetError( 111 error, FROM_HERE, "Already processing an update, cancel it first."); 112 } 113 DCHECK(status_ == UpdateStatus::IDLE); 114 115 std::map<string, string> headers; 116 for (const string& key_value_pair : key_value_pair_headers) { 117 string key; 118 string value; 119 if (!brillo::string_utils::SplitAtFirst( 120 key_value_pair, "=", &key, &value, false)) { 121 return LogAndSetError( 122 error, FROM_HERE, "Passed invalid header: " + key_value_pair); 123 } 124 if (!headers.emplace(key, value).second) 125 return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key); 126 } 127 128 // Unique identifier for the payload. An empty string means that the payload 129 // can't be resumed. 130 string payload_id = (headers[kPayloadPropertyFileHash] + 131 headers[kPayloadPropertyMetadataHash]); 132 133 // Setup the InstallPlan based on the request. 134 install_plan_ = InstallPlan(); 135 136 install_plan_.download_url = payload_url; 137 install_plan_.version = ""; 138 base_offset_ = payload_offset; 139 install_plan_.payload_size = payload_size; 140 if (!install_plan_.payload_size) { 141 if (!base::StringToUint64(headers[kPayloadPropertyFileSize], 142 &install_plan_.payload_size)) { 143 install_plan_.payload_size = 0; 144 } 145 } 146 install_plan_.payload_hash = headers[kPayloadPropertyFileHash]; 147 if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize], 148 &install_plan_.metadata_size)) { 149 install_plan_.metadata_size = 0; 150 } 151 install_plan_.metadata_signature = ""; 152 // The |public_key_rsa| key would override the public key stored on disk. 153 install_plan_.public_key_rsa = ""; 154 155 install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild(); 156 install_plan_.is_resume = !payload_id.empty() && 157 DeltaPerformer::CanResumeUpdate(prefs_, payload_id); 158 if (!install_plan_.is_resume) { 159 if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) { 160 LOG(WARNING) << "Unable to reset the update progress."; 161 } 162 if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) { 163 LOG(WARNING) << "Unable to save the update check response hash."; 164 } 165 } 166 // The |payload_type| is not used anymore since minor_version 3. 167 install_plan_.payload_type = InstallPayloadType::kUnknown; 168 169 install_plan_.source_slot = boot_control_->GetCurrentSlot(); 170 install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0; 171 172 int data_wipe = 0; 173 install_plan_.powerwash_required = 174 base::StringToInt(headers[kPayloadPropertyPowerwash], &data_wipe) && 175 data_wipe != 0; 176 177 LOG(INFO) << "Using this install plan:"; 178 install_plan_.Dump(); 179 180 BuildUpdateActions(); 181 SetupDownload(); 182 // Setup extra headers. 183 HttpFetcher* fetcher = download_action_->http_fetcher(); 184 if (!headers[kPayloadPropertyAuthorization].empty()) 185 fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]); 186 if (!headers[kPayloadPropertyUserAgent].empty()) 187 fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]); 188 189 cpu_limiter_.StartLimiter(); 190 SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE); 191 ongoing_update_ = true; 192 193 // Just in case we didn't update boot flags yet, make sure they're updated 194 // before any update processing starts. This will start the update process. 195 UpdateBootFlags(); 196 return true; 197} 198 199bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) { 200 if (!ongoing_update_) 201 return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend."); 202 processor_->SuspendProcessing(); 203 return true; 204} 205 206bool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) { 207 if (!ongoing_update_) 208 return LogAndSetError(error, FROM_HERE, "No ongoing update to resume."); 209 processor_->ResumeProcessing(); 210 return true; 211} 212 213bool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) { 214 if (!ongoing_update_) 215 return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel."); 216 processor_->StopProcessing(); 217 return true; 218} 219 220bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) { 221 LOG(INFO) << "Attempting to reset state from " 222 << UpdateStatusToString(status_) << " to UpdateStatus::IDLE"; 223 224 switch (status_) { 225 case UpdateStatus::IDLE: 226 return true; 227 228 case UpdateStatus::UPDATED_NEED_REBOOT: { 229 // Remove the reboot marker so that if the machine is rebooted 230 // after resetting to idle state, it doesn't go back to 231 // UpdateStatus::UPDATED_NEED_REBOOT state. 232 bool ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId); 233 234 // Update the boot flags so the current slot has higher priority. 235 if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot())) 236 ret_value = false; 237 238 if (!ret_value) { 239 return LogAndSetError( 240 error, 241 FROM_HERE, 242 "Failed to reset the status to "); 243 } 244 245 SetStatusAndNotify(UpdateStatus::IDLE); 246 LOG(INFO) << "Reset status successful"; 247 return true; 248 } 249 250 default: 251 return LogAndSetError( 252 error, 253 FROM_HERE, 254 "Reset not allowed in this state. Cancel the ongoing update first"); 255 } 256} 257 258void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor, 259 ErrorCode code) { 260 LOG(INFO) << "Processing Done."; 261 262 if (code == ErrorCode::kSuccess) { 263 // Update succeeded. 264 WriteUpdateCompletedMarker(); 265 prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0); 266 DeltaPerformer::ResetUpdateProgress(prefs_, false); 267 268 LOG(INFO) << "Update successfully applied, waiting to reboot."; 269 } 270 271 TerminateUpdateAndNotify(code); 272} 273 274void UpdateAttempterAndroid::ProcessingStopped( 275 const ActionProcessor* processor) { 276 TerminateUpdateAndNotify(ErrorCode::kUserCanceled); 277} 278 279void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor, 280 AbstractAction* action, 281 ErrorCode code) { 282 // Reset download progress regardless of whether or not the download 283 // action succeeded. 284 const string type = action->Type(); 285 if (type == DownloadAction::StaticType()) { 286 download_progress_ = 0; 287 } 288 if (code != ErrorCode::kSuccess) { 289 // If an action failed, the ActionProcessor will cancel the whole thing. 290 return; 291 } 292 if (type == DownloadAction::StaticType()) { 293 SetStatusAndNotify(UpdateStatus::FINALIZING); 294 } 295} 296 297void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed, 298 uint64_t bytes_received, 299 uint64_t total) { 300 double progress = 0; 301 if (total) 302 progress = static_cast<double>(bytes_received) / static_cast<double>(total); 303 if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) { 304 download_progress_ = progress; 305 SetStatusAndNotify(UpdateStatus::DOWNLOADING); 306 } else { 307 ProgressUpdate(progress); 308 } 309} 310 311bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) { 312 // TODO(deymo): Notify the DownloadAction that it should cancel the update 313 // download. 314 return false; 315} 316 317void UpdateAttempterAndroid::DownloadComplete() { 318 // Nothing needs to be done when the download completes. 319} 320 321void UpdateAttempterAndroid::ProgressUpdate(double progress) { 322 // Self throttle based on progress. Also send notifications if progress is 323 // too slow. 324 if (progress == 1.0 || 325 progress - download_progress_ >= kBroadcastThresholdProgress || 326 TimeTicks::Now() - last_notify_time_ >= 327 TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) { 328 download_progress_ = progress; 329 SetStatusAndNotify(status_); 330 } 331} 332 333void UpdateAttempterAndroid::UpdateBootFlags() { 334 if (updated_boot_flags_) { 335 LOG(INFO) << "Already updated boot flags. Skipping."; 336 CompleteUpdateBootFlags(true); 337 return; 338 } 339 // This is purely best effort. 340 LOG(INFO) << "Marking booted slot as good."; 341 if (!boot_control_->MarkBootSuccessfulAsync( 342 Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags, 343 base::Unretained(this)))) { 344 LOG(ERROR) << "Failed to mark current boot as successful."; 345 CompleteUpdateBootFlags(false); 346 } 347} 348 349void UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) { 350 updated_boot_flags_ = true; 351 ScheduleProcessingStart(); 352} 353 354void UpdateAttempterAndroid::ScheduleProcessingStart() { 355 LOG(INFO) << "Scheduling an action processor start."; 356 brillo::MessageLoop::current()->PostTask( 357 FROM_HERE, Bind([this] { this->processor_->StartProcessing(); })); 358} 359 360void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) { 361 if (status_ == UpdateStatus::IDLE) { 362 LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called."; 363 return; 364 } 365 366 // Reset cpu shares back to normal. 367 cpu_limiter_.StopLimiter(); 368 download_progress_ = 0; 369 actions_.clear(); 370 UpdateStatus new_status = 371 (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT 372 : UpdateStatus::IDLE); 373 SetStatusAndNotify(new_status); 374 ongoing_update_ = false; 375 376 for (auto observer : daemon_state_->service_observers()) 377 observer->SendPayloadApplicationComplete(error_code); 378} 379 380void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) { 381 status_ = status; 382 for (auto observer : daemon_state_->service_observers()) { 383 observer->SendStatusUpdate( 384 0, download_progress_, status_, "", install_plan_.payload_size); 385 } 386 last_notify_time_ = TimeTicks::Now(); 387} 388 389void UpdateAttempterAndroid::BuildUpdateActions() { 390 CHECK(!processor_->IsRunning()); 391 processor_->set_delegate(this); 392 393 // Actions: 394 shared_ptr<InstallPlanAction> install_plan_action( 395 new InstallPlanAction(install_plan_)); 396 397 LibcurlHttpFetcher* download_fetcher = 398 new LibcurlHttpFetcher(&proxy_resolver_, hardware_); 399 download_fetcher->set_server_to_check(ServerToCheck::kDownload); 400 shared_ptr<DownloadAction> download_action(new DownloadAction( 401 prefs_, 402 boot_control_, 403 hardware_, 404 nullptr, // system_state, not used. 405 new MultiRangeHttpFetcher(download_fetcher))); // passes ownership 406 shared_ptr<FilesystemVerifierAction> dst_filesystem_verifier_action( 407 new FilesystemVerifierAction(boot_control_, 408 VerifierMode::kVerifyTargetHash)); 409 410 shared_ptr<PostinstallRunnerAction> postinstall_runner_action( 411 new PostinstallRunnerAction(boot_control_, hardware_)); 412 413 download_action->set_delegate(this); 414 download_action_ = download_action; 415 postinstall_runner_action->set_delegate(this); 416 417 actions_.push_back(shared_ptr<AbstractAction>(install_plan_action)); 418 actions_.push_back(shared_ptr<AbstractAction>(download_action)); 419 actions_.push_back( 420 shared_ptr<AbstractAction>(dst_filesystem_verifier_action)); 421 actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action)); 422 423 // Bond them together. We have to use the leaf-types when calling 424 // BondActions(). 425 BondActions(install_plan_action.get(), download_action.get()); 426 BondActions(download_action.get(), dst_filesystem_verifier_action.get()); 427 BondActions(dst_filesystem_verifier_action.get(), 428 postinstall_runner_action.get()); 429 430 // Enqueue the actions. 431 for (const shared_ptr<AbstractAction>& action : actions_) 432 processor_->EnqueueAction(action.get()); 433} 434 435void UpdateAttempterAndroid::SetupDownload() { 436 MultiRangeHttpFetcher* fetcher = 437 static_cast<MultiRangeHttpFetcher*>(download_action_->http_fetcher()); 438 fetcher->ClearRanges(); 439 if (install_plan_.is_resume) { 440 // Resuming an update so fetch the update manifest metadata first. 441 int64_t manifest_metadata_size = 0; 442 int64_t manifest_signature_size = 0; 443 prefs_->GetInt64(kPrefsManifestMetadataSize, &manifest_metadata_size); 444 prefs_->GetInt64(kPrefsManifestSignatureSize, &manifest_signature_size); 445 fetcher->AddRange(base_offset_, 446 manifest_metadata_size + manifest_signature_size); 447 // If there're remaining unprocessed data blobs, fetch them. Be careful not 448 // to request data beyond the end of the payload to avoid 416 HTTP response 449 // error codes. 450 int64_t next_data_offset = 0; 451 prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, &next_data_offset); 452 uint64_t resume_offset = 453 manifest_metadata_size + manifest_signature_size + next_data_offset; 454 if (!install_plan_.payload_size) { 455 fetcher->AddRange(base_offset_ + resume_offset); 456 } else if (resume_offset < install_plan_.payload_size) { 457 fetcher->AddRange(base_offset_ + resume_offset, 458 install_plan_.payload_size - resume_offset); 459 } 460 } else { 461 if (install_plan_.payload_size) { 462 fetcher->AddRange(base_offset_, install_plan_.payload_size); 463 } else { 464 // If no payload size is passed we assume we read until the end of the 465 // stream. 466 fetcher->AddRange(base_offset_); 467 } 468 } 469} 470 471bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() { 472 string boot_id; 473 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id)); 474 prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id); 475 return true; 476} 477 478bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() { 479 // In case of an update_engine restart without a reboot, we stored the boot_id 480 // when the update was completed by setting a pref, so we can check whether 481 // the last update was on this boot or a previous one. 482 string boot_id; 483 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id)); 484 485 string update_completed_on_boot_id; 486 return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) && 487 prefs_->GetString(kPrefsUpdateCompletedOnBootId, 488 &update_completed_on_boot_id) && 489 update_completed_on_boot_id == boot_id); 490} 491 492} // namespace chromeos_update_engine 493