update_attempter_android.cc revision e6e4bb929acd73e57b68a30d1e3a33d76607aec3
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 install_plan_.powerwash_required = false; 172 173 LOG(INFO) << "Using this install plan:"; 174 install_plan_.Dump(); 175 176 BuildUpdateActions(); 177 SetupDownload(); 178 // Setup extra headers. 179 HttpFetcher* fetcher = download_action_->http_fetcher(); 180 if (!headers[kPayloadPropertyAuthorization].empty()) 181 fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]); 182 if (!headers[kPayloadPropertyUserAgent].empty()) 183 fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]); 184 185 cpu_limiter_.StartLimiter(); 186 SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE); 187 ongoing_update_ = true; 188 189 // Just in case we didn't update boot flags yet, make sure they're updated 190 // before any update processing starts. This will start the update process. 191 UpdateBootFlags(); 192 return true; 193} 194 195bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) { 196 if (!ongoing_update_) 197 return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend."); 198 processor_->SuspendProcessing(); 199 return true; 200} 201 202bool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) { 203 if (!ongoing_update_) 204 return LogAndSetError(error, FROM_HERE, "No ongoing update to resume."); 205 processor_->ResumeProcessing(); 206 return true; 207} 208 209bool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) { 210 if (!ongoing_update_) 211 return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel."); 212 processor_->StopProcessing(); 213 return true; 214} 215 216bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) { 217 LOG(INFO) << "Attempting to reset state from " 218 << UpdateStatusToString(status_) << " to UpdateStatus::IDLE"; 219 220 switch (status_) { 221 case UpdateStatus::IDLE: 222 return true; 223 224 case UpdateStatus::UPDATED_NEED_REBOOT: { 225 // Remove the reboot marker so that if the machine is rebooted 226 // after resetting to idle state, it doesn't go back to 227 // UpdateStatus::UPDATED_NEED_REBOOT state. 228 bool ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId); 229 230 // Update the boot flags so the current slot has higher priority. 231 if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot())) 232 ret_value = false; 233 234 if (!ret_value) { 235 return LogAndSetError( 236 error, 237 FROM_HERE, 238 "Failed to reset the status to "); 239 } 240 241 SetStatusAndNotify(UpdateStatus::IDLE); 242 LOG(INFO) << "Reset status successful"; 243 return true; 244 } 245 246 default: 247 return LogAndSetError( 248 error, 249 FROM_HERE, 250 "Reset not allowed in this state. Cancel the ongoing update first"); 251 } 252} 253 254void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor, 255 ErrorCode code) { 256 LOG(INFO) << "Processing Done."; 257 258 if (code == ErrorCode::kSuccess) { 259 // Update succeeded. 260 WriteUpdateCompletedMarker(); 261 prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0); 262 DeltaPerformer::ResetUpdateProgress(prefs_, false); 263 264 LOG(INFO) << "Update successfully applied, waiting to reboot."; 265 } 266 267 TerminateUpdateAndNotify(code); 268} 269 270void UpdateAttempterAndroid::ProcessingStopped( 271 const ActionProcessor* processor) { 272 TerminateUpdateAndNotify(ErrorCode::kUserCanceled); 273} 274 275void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor, 276 AbstractAction* action, 277 ErrorCode code) { 278 // Reset download progress regardless of whether or not the download 279 // action succeeded. 280 const string type = action->Type(); 281 if (type == DownloadAction::StaticType()) { 282 download_progress_ = 0; 283 } 284 if (code != ErrorCode::kSuccess) { 285 // If an action failed, the ActionProcessor will cancel the whole thing. 286 return; 287 } 288 if (type == DownloadAction::StaticType()) { 289 SetStatusAndNotify(UpdateStatus::FINALIZING); 290 } 291} 292 293void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed, 294 uint64_t bytes_received, 295 uint64_t total) { 296 double progress = 0; 297 if (total) 298 progress = static_cast<double>(bytes_received) / static_cast<double>(total); 299 if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) { 300 download_progress_ = progress; 301 SetStatusAndNotify(UpdateStatus::DOWNLOADING); 302 } else { 303 ProgressUpdate(progress); 304 } 305} 306 307bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) { 308 // TODO(deymo): Notify the DownloadAction that it should cancel the update 309 // download. 310 return false; 311} 312 313void UpdateAttempterAndroid::DownloadComplete() { 314 // Nothing needs to be done when the download completes. 315} 316 317void UpdateAttempterAndroid::ProgressUpdate(double progress) { 318 // Self throttle based on progress. Also send notifications if progress is 319 // too slow. 320 if (progress == 1.0 || 321 progress - download_progress_ >= kBroadcastThresholdProgress || 322 TimeTicks::Now() - last_notify_time_ >= 323 TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) { 324 download_progress_ = progress; 325 SetStatusAndNotify(status_); 326 } 327} 328 329void UpdateAttempterAndroid::UpdateBootFlags() { 330 if (updated_boot_flags_) { 331 LOG(INFO) << "Already updated boot flags. Skipping."; 332 CompleteUpdateBootFlags(true); 333 return; 334 } 335 // This is purely best effort. 336 LOG(INFO) << "Marking booted slot as good."; 337 if (!boot_control_->MarkBootSuccessfulAsync( 338 Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags, 339 base::Unretained(this)))) { 340 LOG(ERROR) << "Failed to mark current boot as successful."; 341 CompleteUpdateBootFlags(false); 342 } 343} 344 345void UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) { 346 updated_boot_flags_ = true; 347 ScheduleProcessingStart(); 348} 349 350void UpdateAttempterAndroid::ScheduleProcessingStart() { 351 LOG(INFO) << "Scheduling an action processor start."; 352 brillo::MessageLoop::current()->PostTask( 353 FROM_HERE, Bind([this] { this->processor_->StartProcessing(); })); 354} 355 356void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) { 357 if (status_ == UpdateStatus::IDLE) { 358 LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called."; 359 return; 360 } 361 362 // Reset cpu shares back to normal. 363 cpu_limiter_.StopLimiter(); 364 download_progress_ = 0; 365 actions_.clear(); 366 UpdateStatus new_status = 367 (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT 368 : UpdateStatus::IDLE); 369 SetStatusAndNotify(new_status); 370 ongoing_update_ = false; 371 372 for (auto observer : daemon_state_->service_observers()) 373 observer->SendPayloadApplicationComplete(error_code); 374} 375 376void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) { 377 status_ = status; 378 for (auto observer : daemon_state_->service_observers()) { 379 observer->SendStatusUpdate( 380 0, download_progress_, status_, "", install_plan_.payload_size); 381 } 382 last_notify_time_ = TimeTicks::Now(); 383} 384 385void UpdateAttempterAndroid::BuildUpdateActions() { 386 CHECK(!processor_->IsRunning()); 387 processor_->set_delegate(this); 388 389 // Actions: 390 shared_ptr<InstallPlanAction> install_plan_action( 391 new InstallPlanAction(install_plan_)); 392 393 LibcurlHttpFetcher* download_fetcher = 394 new LibcurlHttpFetcher(&proxy_resolver_, hardware_); 395 download_fetcher->set_server_to_check(ServerToCheck::kDownload); 396 shared_ptr<DownloadAction> download_action(new DownloadAction( 397 prefs_, 398 boot_control_, 399 hardware_, 400 nullptr, // system_state, not used. 401 new MultiRangeHttpFetcher(download_fetcher))); // passes ownership 402 shared_ptr<FilesystemVerifierAction> filesystem_verifier_action( 403 new FilesystemVerifierAction()); 404 405 shared_ptr<PostinstallRunnerAction> postinstall_runner_action( 406 new PostinstallRunnerAction(boot_control_)); 407 408 download_action->set_delegate(this); 409 download_action_ = download_action; 410 411 actions_.push_back(shared_ptr<AbstractAction>(install_plan_action)); 412 actions_.push_back(shared_ptr<AbstractAction>(download_action)); 413 actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action)); 414 actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action)); 415 416 // Bond them together. We have to use the leaf-types when calling 417 // BondActions(). 418 BondActions(install_plan_action.get(), download_action.get()); 419 BondActions(download_action.get(), filesystem_verifier_action.get()); 420 BondActions(filesystem_verifier_action.get(), 421 postinstall_runner_action.get()); 422 423 // Enqueue the actions. 424 for (const shared_ptr<AbstractAction>& action : actions_) 425 processor_->EnqueueAction(action.get()); 426} 427 428void UpdateAttempterAndroid::SetupDownload() { 429 MultiRangeHttpFetcher* fetcher = 430 static_cast<MultiRangeHttpFetcher*>(download_action_->http_fetcher()); 431 fetcher->ClearRanges(); 432 if (install_plan_.is_resume) { 433 // Resuming an update so fetch the update manifest metadata first. 434 int64_t manifest_metadata_size = 0; 435 int64_t manifest_signature_size = 0; 436 prefs_->GetInt64(kPrefsManifestMetadataSize, &manifest_metadata_size); 437 prefs_->GetInt64(kPrefsManifestSignatureSize, &manifest_signature_size); 438 fetcher->AddRange(base_offset_, 439 manifest_metadata_size + manifest_signature_size); 440 // If there're remaining unprocessed data blobs, fetch them. Be careful not 441 // to request data beyond the end of the payload to avoid 416 HTTP response 442 // error codes. 443 int64_t next_data_offset = 0; 444 prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, &next_data_offset); 445 uint64_t resume_offset = 446 manifest_metadata_size + manifest_signature_size + next_data_offset; 447 if (!install_plan_.payload_size) { 448 fetcher->AddRange(base_offset_ + resume_offset); 449 } else if (resume_offset < install_plan_.payload_size) { 450 fetcher->AddRange(base_offset_ + resume_offset, 451 install_plan_.payload_size - resume_offset); 452 } 453 } else { 454 if (install_plan_.payload_size) { 455 fetcher->AddRange(base_offset_, install_plan_.payload_size); 456 } else { 457 // If no payload size is passed we assume we read until the end of the 458 // stream. 459 fetcher->AddRange(base_offset_); 460 } 461 } 462} 463 464bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() { 465 string boot_id; 466 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id)); 467 prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id); 468 return true; 469} 470 471bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() { 472 // In case of an update_engine restart without a reboot, we stored the boot_id 473 // when the update was completed by setting a pref, so we can check whether 474 // the last update was on this boot or a previous one. 475 string boot_id; 476 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id)); 477 478 string update_completed_on_boot_id; 479 return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) && 480 prefs_->GetString(kPrefsUpdateCompletedOnBootId, 481 &update_completed_on_boot_id) && 482 update_completed_on_boot_id == boot_id); 483} 484 485} // namespace chromeos_update_engine 486