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/aosp/update_attempter_android.h"
18
19 #include <algorithm>
20 #include <map>
21 #include <memory>
22 #include <utility>
23
24 #include <android-base/properties.h>
25 #include <android-base/unique_fd.h>
26 #include <base/bind.h>
27 #include <base/logging.h>
28 #include <base/strings/string_number_conversions.h>
29 #include <brillo/data_encoding.h>
30 #include <brillo/message_loops/message_loop.h>
31 #include <brillo/strings/string_utils.h>
32 #include <log/log_safetynet.h>
33
34 #include "update_engine/aosp/cleanup_previous_update_action.h"
35 #include "update_engine/common/constants.h"
36 #include "update_engine/common/daemon_state_interface.h"
37 #include "update_engine/common/download_action.h"
38 #include "update_engine/common/error_code_utils.h"
39 #include "update_engine/common/file_fetcher.h"
40 #include "update_engine/common/metrics_reporter_interface.h"
41 #include "update_engine/common/network_selector.h"
42 #include "update_engine/common/utils.h"
43 #include "update_engine/metrics_utils.h"
44 #include "update_engine/payload_consumer/certificate_parser_interface.h"
45 #include "update_engine/payload_consumer/delta_performer.h"
46 #include "update_engine/payload_consumer/file_descriptor.h"
47 #include "update_engine/payload_consumer/file_descriptor_utils.h"
48 #include "update_engine/payload_consumer/filesystem_verifier_action.h"
49 #include "update_engine/payload_consumer/payload_constants.h"
50 #include "update_engine/payload_consumer/payload_metadata.h"
51 #include "update_engine/payload_consumer/payload_verifier.h"
52 #include "update_engine/payload_consumer/postinstall_runner_action.h"
53 #include "update_engine/update_boot_flags_action.h"
54 #include "update_engine/update_status_utils.h"
55
56 #ifndef _UE_SIDELOAD
57 // Do not include support for external HTTP(s) urls when building
58 // update_engine_sideload.
59 #include "update_engine/libcurl_http_fetcher.h"
60 #endif
61
62 using android::base::unique_fd;
63 using base::Bind;
64 using base::Time;
65 using base::TimeDelta;
66 using base::TimeTicks;
67 using std::string;
68 using std::vector;
69 using update_engine::UpdateEngineStatus;
70
71 namespace chromeos_update_engine {
72
73 namespace {
74
75 // Minimum threshold to broadcast an status update in progress and time.
76 const double kBroadcastThresholdProgress = 0.01; // 1%
77 const int kBroadcastThresholdSeconds = 10;
78
79 const char* const kErrorDomain = "update_engine";
80 // TODO(deymo): Convert the different errors to a numeric value to report them
81 // back on the service error.
82 const char* const kGenericError = "generic_error";
83
84 // Log and set the error on the passed ErrorPtr.
LogAndSetError(brillo::ErrorPtr * error,const base::Location & location,const string & reason)85 bool LogAndSetError(brillo::ErrorPtr* error,
86 const base::Location& location,
87 const string& reason) {
88 brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason);
89 LOG(ERROR) << "Replying with failure: " << location.ToString() << ": "
90 << reason;
91 return false;
92 }
93
GetHeaderAsBool(const string & header,bool default_value)94 bool GetHeaderAsBool(const string& header, bool default_value) {
95 int value = 0;
96 if (base::StringToInt(header, &value) && (value == 0 || value == 1))
97 return value == 1;
98 return default_value;
99 }
100
ParseKeyValuePairHeaders(const vector<string> & key_value_pair_headers,std::map<string,string> * headers,brillo::ErrorPtr * error)101 bool ParseKeyValuePairHeaders(const vector<string>& key_value_pair_headers,
102 std::map<string, string>* headers,
103 brillo::ErrorPtr* error) {
104 for (const string& key_value_pair : key_value_pair_headers) {
105 string key;
106 string value;
107 if (!brillo::string_utils::SplitAtFirst(
108 key_value_pair, "=", &key, &value, false)) {
109 return LogAndSetError(
110 error, FROM_HERE, "Passed invalid header: " + key_value_pair);
111 }
112 if (!headers->emplace(key, value).second)
113 return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key);
114 }
115 return true;
116 }
117
118 // Unique identifier for the payload. An empty string means that the payload
119 // can't be resumed.
GetPayloadId(const std::map<string,string> & headers)120 string GetPayloadId(const std::map<string, string>& headers) {
121 return (headers.count(kPayloadPropertyFileHash)
122 ? headers.at(kPayloadPropertyFileHash)
123 : "") +
124 (headers.count(kPayloadPropertyMetadataHash)
125 ? headers.at(kPayloadPropertyMetadataHash)
126 : "");
127 }
128
129 } // namespace
130
UpdateAttempterAndroid(DaemonStateInterface * daemon_state,PrefsInterface * prefs,BootControlInterface * boot_control,HardwareInterface * hardware,std::unique_ptr<ApexHandlerInterface> apex_handler)131 UpdateAttempterAndroid::UpdateAttempterAndroid(
132 DaemonStateInterface* daemon_state,
133 PrefsInterface* prefs,
134 BootControlInterface* boot_control,
135 HardwareInterface* hardware,
136 std::unique_ptr<ApexHandlerInterface> apex_handler)
137 : daemon_state_(daemon_state),
138 prefs_(prefs),
139 boot_control_(boot_control),
140 hardware_(hardware),
141 apex_handler_android_(std::move(apex_handler)),
142 processor_(new ActionProcessor()),
143 clock_(new Clock()) {
144 metrics_reporter_ = metrics::CreateMetricsReporter(
145 boot_control_->GetDynamicPartitionControl(), &install_plan_);
146 network_selector_ = network::CreateNetworkSelector();
147 }
148
~UpdateAttempterAndroid()149 UpdateAttempterAndroid::~UpdateAttempterAndroid() {
150 // Release ourselves as the ActionProcessor's delegate to prevent
151 // re-scheduling the updates due to the processing stopped.
152 processor_->set_delegate(nullptr);
153 }
154
Init()155 void UpdateAttempterAndroid::Init() {
156 // In case of update_engine restart without a reboot we need to restore the
157 // reboot needed state.
158 if (UpdateCompletedOnThisBoot()) {
159 SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
160 } else {
161 SetStatusAndNotify(UpdateStatus::IDLE);
162 UpdatePrefsAndReportUpdateMetricsOnReboot();
163 #ifdef _UE_SIDELOAD
164 LOG(INFO) << "Skip ScheduleCleanupPreviousUpdate in sideload because "
165 << "ApplyPayload will call it later.";
166 #else
167 ScheduleCleanupPreviousUpdate();
168 #endif
169 }
170 }
171
ApplyPayload(const string & payload_url,int64_t payload_offset,int64_t payload_size,const vector<string> & key_value_pair_headers,brillo::ErrorPtr * error)172 bool UpdateAttempterAndroid::ApplyPayload(
173 const string& payload_url,
174 int64_t payload_offset,
175 int64_t payload_size,
176 const vector<string>& key_value_pair_headers,
177 brillo::ErrorPtr* error) {
178 if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
179 return LogAndSetError(
180 error, FROM_HERE, "An update already applied, waiting for reboot");
181 }
182 if (processor_->IsRunning()) {
183 return LogAndSetError(
184 error, FROM_HERE, "Already processing an update, cancel it first.");
185 }
186 DCHECK_EQ(status_, UpdateStatus::IDLE);
187
188 std::map<string, string> headers;
189 if (!ParseKeyValuePairHeaders(key_value_pair_headers, &headers, error)) {
190 return false;
191 }
192
193 string payload_id = GetPayloadId(headers);
194
195 // Setup the InstallPlan based on the request.
196 install_plan_ = InstallPlan();
197
198 install_plan_.download_url = payload_url;
199 install_plan_.version = "";
200 base_offset_ = payload_offset;
201 InstallPlan::Payload payload;
202 payload.size = payload_size;
203 if (!payload.size) {
204 if (!base::StringToUint64(headers[kPayloadPropertyFileSize],
205 &payload.size)) {
206 payload.size = 0;
207 }
208 }
209 if (!brillo::data_encoding::Base64Decode(headers[kPayloadPropertyFileHash],
210 &payload.hash)) {
211 LOG(WARNING) << "Unable to decode base64 file hash: "
212 << headers[kPayloadPropertyFileHash];
213 }
214 if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize],
215 &payload.metadata_size)) {
216 payload.metadata_size = 0;
217 }
218 // The |payload.type| is not used anymore since minor_version 3.
219 payload.type = InstallPayloadType::kUnknown;
220 install_plan_.payloads.push_back(payload);
221
222 // The |public_key_rsa| key would override the public key stored on disk.
223 install_plan_.public_key_rsa = "";
224
225 install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
226 install_plan_.is_resume = !payload_id.empty() &&
227 DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
228 if (!install_plan_.is_resume) {
229 // No need to reset dynamic_partititon_metadata_updated. If previous calls
230 // to AllocateSpaceForPayload uses the same payload_id, reuse preallocated
231 // space. Otherwise, DeltaPerformer re-allocates space when the payload is
232 // applied.
233 if (!DeltaPerformer::ResetUpdateProgress(
234 prefs_,
235 false /* quick */,
236 true /* skip_dynamic_partititon_metadata_updated */)) {
237 LOG(WARNING) << "Unable to reset the update progress.";
238 }
239 if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
240 LOG(WARNING) << "Unable to save the update check response hash.";
241 }
242 }
243 install_plan_.source_slot = GetCurrentSlot();
244 install_plan_.target_slot = GetTargetSlot();
245
246 install_plan_.powerwash_required =
247 GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false);
248
249 install_plan_.switch_slot_on_reboot =
250 GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true);
251
252 install_plan_.run_post_install =
253 GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
254
255 // Skip writing verity if we're resuming and verity has already been written.
256 install_plan_.write_verity = true;
257 if (install_plan_.is_resume && prefs_->Exists(kPrefsVerityWritten)) {
258 bool verity_written = false;
259 if (prefs_->GetBoolean(kPrefsVerityWritten, &verity_written) &&
260 verity_written) {
261 install_plan_.write_verity = false;
262 }
263 }
264
265 NetworkId network_id = kDefaultNetworkId;
266 if (!headers[kPayloadPropertyNetworkId].empty()) {
267 if (!base::StringToUint64(headers[kPayloadPropertyNetworkId],
268 &network_id)) {
269 return LogAndSetError(
270 error,
271 FROM_HERE,
272 "Invalid network_id: " + headers[kPayloadPropertyNetworkId]);
273 }
274 if (!network_selector_->SetProcessNetwork(network_id)) {
275 return LogAndSetError(
276 error,
277 FROM_HERE,
278 "Unable to set network_id: " + headers[kPayloadPropertyNetworkId]);
279 }
280 }
281
282 LOG(INFO) << "Using this install plan:";
283 install_plan_.Dump();
284
285 HttpFetcher* fetcher = nullptr;
286 if (FileFetcher::SupportedUrl(payload_url)) {
287 DLOG(INFO) << "Using FileFetcher for file URL.";
288 fetcher = new FileFetcher();
289 } else {
290 #ifdef _UE_SIDELOAD
291 LOG(FATAL) << "Unsupported sideload URI: " << payload_url;
292 #else
293 LibcurlHttpFetcher* libcurl_fetcher =
294 new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
295 libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
296 fetcher = libcurl_fetcher;
297 #endif // _UE_SIDELOAD
298 }
299 // Setup extra headers.
300 if (!headers[kPayloadPropertyAuthorization].empty())
301 fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]);
302 if (!headers[kPayloadPropertyUserAgent].empty())
303 fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
304
305 BuildUpdateActions(fetcher);
306
307 SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
308
309 UpdatePrefsOnUpdateStart(install_plan_.is_resume);
310 // TODO(xunchang) report the metrics for unresumable updates
311
312 ScheduleProcessingStart();
313 return true;
314 }
315
ApplyPayload(int fd,int64_t payload_offset,int64_t payload_size,const vector<string> & key_value_pair_headers,brillo::ErrorPtr * error)316 bool UpdateAttempterAndroid::ApplyPayload(
317 int fd,
318 int64_t payload_offset,
319 int64_t payload_size,
320 const vector<string>& key_value_pair_headers,
321 brillo::ErrorPtr* error) {
322 // update_engine state must be checked before modifying payload_fd_ otherwise
323 // already running update will be terminated (existing file descriptor will be
324 // closed)
325 if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
326 return LogAndSetError(
327 error, FROM_HERE, "An update already applied, waiting for reboot");
328 }
329 if (processor_->IsRunning()) {
330 return LogAndSetError(
331 error, FROM_HERE, "Already processing an update, cancel it first.");
332 }
333 DCHECK_EQ(status_, UpdateStatus::IDLE);
334
335 payload_fd_.reset(dup(fd));
336 const string payload_url = "fd://" + std::to_string(payload_fd_.get());
337
338 return ApplyPayload(
339 payload_url, payload_offset, payload_size, key_value_pair_headers, error);
340 }
341
SuspendUpdate(brillo::ErrorPtr * error)342 bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) {
343 if (!processor_->IsRunning())
344 return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend.");
345 processor_->SuspendProcessing();
346 return true;
347 }
348
ResumeUpdate(brillo::ErrorPtr * error)349 bool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) {
350 if (!processor_->IsRunning())
351 return LogAndSetError(error, FROM_HERE, "No ongoing update to resume.");
352 processor_->ResumeProcessing();
353 return true;
354 }
355
CancelUpdate(brillo::ErrorPtr * error)356 bool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) {
357 if (!processor_->IsRunning())
358 return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel.");
359 processor_->StopProcessing();
360 return true;
361 }
362
ResetStatus(brillo::ErrorPtr * error)363 bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) {
364 LOG(INFO) << "Attempting to reset state from "
365 << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
366
367 if (apex_handler_android_ != nullptr) {
368 LOG(INFO) << "Cleaning up reserved space for compressed APEX (if any)";
369 std::vector<ApexInfo> apex_infos_blank;
370 apex_handler_android_->AllocateSpace(apex_infos_blank);
371 }
372
373 switch (status_) {
374 case UpdateStatus::IDLE: {
375 if (!boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_)) {
376 LOG(WARNING) << "Failed to reset snapshots. UpdateStatus is IDLE but"
377 << "space might not be freed.";
378 }
379 return true;
380 }
381
382 case UpdateStatus::UPDATED_NEED_REBOOT: {
383 bool ret_value = true;
384
385 // Update the boot flags so the current slot has higher priority.
386 if (!boot_control_->SetActiveBootSlot(GetCurrentSlot()))
387 ret_value = false;
388
389 // Mark the current slot as successful again, since marking it as active
390 // may reset the successful bit. We ignore the result of whether marking
391 // the current slot as successful worked.
392 if (!boot_control_->MarkBootSuccessfulAsync(Bind([](bool successful) {})))
393 ret_value = false;
394
395 // Resets the warm reset property since we won't switch the slot.
396 hardware_->SetWarmReset(false);
397
398 // Resets the vbmeta digest.
399 hardware_->SetVbmetaDigestForInactiveSlot(true /* reset */);
400
401 // Remove update progress for DeltaPerformer and remove snapshots.
402 if (!boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_))
403 ret_value = false;
404
405 // Remove the reboot marker so that if the machine is rebooted
406 // after resetting to idle state, it doesn't go back to
407 // UpdateStatus::UPDATED_NEED_REBOOT state.
408 if (!prefs_->Delete(kPrefsUpdateCompletedOnBootId))
409 ret_value = false;
410 ClearMetricsPrefs();
411
412 if (!ret_value) {
413 return LogAndSetError(
414 error, FROM_HERE, "Failed to reset the status to ");
415 }
416
417 SetStatusAndNotify(UpdateStatus::IDLE);
418 LOG(INFO) << "Reset status successful";
419 return true;
420 }
421
422 default:
423 return LogAndSetError(
424 error,
425 FROM_HERE,
426 "Reset not allowed in this state. Cancel the ongoing update first");
427 }
428 }
429
VerifyPayloadParseManifest(const std::string & metadata_filename,DeltaArchiveManifest * manifest,brillo::ErrorPtr * error)430 bool UpdateAttempterAndroid::VerifyPayloadParseManifest(
431 const std::string& metadata_filename,
432 DeltaArchiveManifest* manifest,
433 brillo::ErrorPtr* error) {
434 FileDescriptorPtr fd(new EintrSafeFileDescriptor);
435 if (!fd->Open(metadata_filename.c_str(), O_RDONLY)) {
436 return LogAndSetError(
437 error, FROM_HERE, "Failed to open " + metadata_filename);
438 }
439 brillo::Blob metadata(kMaxPayloadHeaderSize);
440 if (!fd->Read(metadata.data(), metadata.size())) {
441 return LogAndSetError(
442 error,
443 FROM_HERE,
444 "Failed to read payload header from " + metadata_filename);
445 }
446 ErrorCode errorcode;
447 PayloadMetadata payload_metadata;
448 if (payload_metadata.ParsePayloadHeader(metadata, &errorcode) !=
449 MetadataParseResult::kSuccess) {
450 return LogAndSetError(error,
451 FROM_HERE,
452 "Failed to parse payload header: " +
453 utils::ErrorCodeToString(errorcode));
454 }
455 uint64_t metadata_size = payload_metadata.GetMetadataSize() +
456 payload_metadata.GetMetadataSignatureSize();
457 if (metadata_size < kMaxPayloadHeaderSize ||
458 metadata_size >
459 static_cast<uint64_t>(utils::FileSize(metadata_filename))) {
460 return LogAndSetError(
461 error,
462 FROM_HERE,
463 "Invalid metadata size: " + std::to_string(metadata_size));
464 }
465 metadata.resize(metadata_size);
466 if (!fd->Read(metadata.data() + kMaxPayloadHeaderSize,
467 metadata.size() - kMaxPayloadHeaderSize)) {
468 return LogAndSetError(
469 error,
470 FROM_HERE,
471 "Failed to read metadata and signature from " + metadata_filename);
472 }
473 fd->Close();
474
475 auto payload_verifier = PayloadVerifier::CreateInstanceFromZipPath(
476 constants::kUpdateCertificatesPath);
477 if (!payload_verifier) {
478 return LogAndSetError(error,
479 FROM_HERE,
480 "Failed to create the payload verifier from " +
481 std::string(constants::kUpdateCertificatesPath));
482 }
483 errorcode = payload_metadata.ValidateMetadataSignature(
484 metadata, "", *payload_verifier);
485 if (errorcode != ErrorCode::kSuccess) {
486 return LogAndSetError(error,
487 FROM_HERE,
488 "Failed to validate metadata signature: " +
489 utils::ErrorCodeToString(errorcode));
490 }
491 if (!payload_metadata.GetManifest(metadata, manifest)) {
492 return LogAndSetError(error, FROM_HERE, "Failed to parse manifest.");
493 }
494
495 return true;
496 }
497
VerifyPayloadApplicable(const std::string & metadata_filename,brillo::ErrorPtr * error)498 bool UpdateAttempterAndroid::VerifyPayloadApplicable(
499 const std::string& metadata_filename, brillo::ErrorPtr* error) {
500 DeltaArchiveManifest manifest;
501 TEST_AND_RETURN_FALSE(
502 VerifyPayloadParseManifest(metadata_filename, &manifest, error));
503
504 FileDescriptorPtr fd(new EintrSafeFileDescriptor);
505 ErrorCode errorcode;
506
507 BootControlInterface::Slot current_slot = GetCurrentSlot();
508 for (const PartitionUpdate& partition : manifest.partitions()) {
509 if (!partition.has_old_partition_info())
510 continue;
511 string partition_path;
512 if (!boot_control_->GetPartitionDevice(
513 partition.partition_name(), current_slot, &partition_path)) {
514 return LogAndSetError(
515 error,
516 FROM_HERE,
517 "Failed to get partition device for " + partition.partition_name());
518 }
519 if (!fd->Open(partition_path.c_str(), O_RDONLY)) {
520 return LogAndSetError(
521 error, FROM_HERE, "Failed to open " + partition_path);
522 }
523 for (const InstallOperation& operation : partition.operations()) {
524 if (!operation.has_src_sha256_hash())
525 continue;
526 brillo::Blob source_hash;
527 if (!fd_utils::ReadAndHashExtents(fd,
528 operation.src_extents(),
529 manifest.block_size(),
530 &source_hash)) {
531 return LogAndSetError(
532 error, FROM_HERE, "Failed to hash " + partition_path);
533 }
534 if (!PartitionWriter::ValidateSourceHash(
535 source_hash, operation, fd, &errorcode)) {
536 return false;
537 }
538 }
539 fd->Close();
540 }
541 return true;
542 }
543
ProcessingDone(const ActionProcessor * processor,ErrorCode code)544 void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
545 ErrorCode code) {
546 LOG(INFO) << "Processing Done.";
547
548 if (status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE) {
549 TerminateUpdateAndNotify(code);
550 return;
551 }
552
553 switch (code) {
554 case ErrorCode::kSuccess:
555 // Update succeeded.
556 WriteUpdateCompletedMarker();
557 prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
558
559 LOG(INFO) << "Update successfully applied, waiting to reboot.";
560 break;
561
562 case ErrorCode::kFilesystemCopierError:
563 case ErrorCode::kNewRootfsVerificationError:
564 case ErrorCode::kNewKernelVerificationError:
565 case ErrorCode::kFilesystemVerifierError:
566 case ErrorCode::kDownloadStateInitializationError:
567 // Reset the ongoing update for these errors so it starts from the
568 // beginning next time.
569 DeltaPerformer::ResetUpdateProgress(prefs_, false);
570 LOG(INFO) << "Resetting update progress.";
571 break;
572
573 case ErrorCode::kPayloadTimestampError:
574 // SafetyNet logging, b/36232423
575 android_errorWriteLog(0x534e4554, "36232423");
576 break;
577
578 default:
579 // Ignore all other error codes.
580 break;
581 }
582
583 TerminateUpdateAndNotify(code);
584 }
585
ProcessingStopped(const ActionProcessor * processor)586 void UpdateAttempterAndroid::ProcessingStopped(
587 const ActionProcessor* processor) {
588 TerminateUpdateAndNotify(ErrorCode::kUserCanceled);
589 }
590
ActionCompleted(ActionProcessor * processor,AbstractAction * action,ErrorCode code)591 void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor,
592 AbstractAction* action,
593 ErrorCode code) {
594 // Reset download progress regardless of whether or not the download
595 // action succeeded.
596 const string type = action->Type();
597 if (type == CleanupPreviousUpdateAction::StaticType() ||
598 (type == NoOpAction::StaticType() &&
599 status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE)) {
600 cleanup_previous_update_code_ = code;
601 NotifyCleanupPreviousUpdateCallbacksAndClear();
602 }
603 // download_progress_ is actually used by other actions, such as
604 // filesystem_verify_action. Therefore we always clear it.
605 download_progress_ = 0;
606 if (type == PostinstallRunnerAction::StaticType()) {
607 bool succeeded =
608 code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive;
609 prefs_->SetBoolean(kPrefsPostInstallSucceeded, succeeded);
610 }
611 if (code != ErrorCode::kSuccess) {
612 // If an action failed, the ActionProcessor will cancel the whole thing.
613 return;
614 }
615 if (type == UpdateBootFlagsAction::StaticType()) {
616 SetStatusAndNotify(UpdateStatus::CLEANUP_PREVIOUS_UPDATE);
617 }
618 if (type == DownloadAction::StaticType()) {
619 auto download_action = static_cast<DownloadAction*>(action);
620 install_plan_ = *download_action->install_plan();
621 SetStatusAndNotify(UpdateStatus::VERIFYING);
622 } else if (type == FilesystemVerifierAction::StaticType()) {
623 SetStatusAndNotify(UpdateStatus::FINALIZING);
624 prefs_->SetBoolean(kPrefsVerityWritten, true);
625 }
626 }
627
BytesReceived(uint64_t bytes_progressed,uint64_t bytes_received,uint64_t total)628 void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed,
629 uint64_t bytes_received,
630 uint64_t total) {
631 double progress = 0;
632 if (total)
633 progress = static_cast<double>(bytes_received) / static_cast<double>(total);
634 if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) {
635 download_progress_ = progress;
636 SetStatusAndNotify(UpdateStatus::DOWNLOADING);
637 } else {
638 ProgressUpdate(progress);
639 }
640
641 // Update the bytes downloaded in prefs.
642 int64_t current_bytes_downloaded =
643 metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
644 int64_t total_bytes_downloaded =
645 metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
646 prefs_->SetInt64(kPrefsCurrentBytesDownloaded,
647 current_bytes_downloaded + bytes_progressed);
648 prefs_->SetInt64(kPrefsTotalBytesDownloaded,
649 total_bytes_downloaded + bytes_progressed);
650 }
651
ShouldCancel(ErrorCode * cancel_reason)652 bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
653 // TODO(deymo): Notify the DownloadAction that it should cancel the update
654 // download.
655 return false;
656 }
657
DownloadComplete()658 void UpdateAttempterAndroid::DownloadComplete() {
659 // Nothing needs to be done when the download completes.
660 }
661
ProgressUpdate(double progress)662 void UpdateAttempterAndroid::ProgressUpdate(double progress) {
663 // Self throttle based on progress. Also send notifications if progress is
664 // too slow.
665 if (progress == 1.0 ||
666 progress - download_progress_ >= kBroadcastThresholdProgress ||
667 TimeTicks::Now() - last_notify_time_ >=
668 TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) {
669 download_progress_ = progress;
670 SetStatusAndNotify(status_);
671 }
672 }
673
OnVerifyProgressUpdate(double progress)674 void UpdateAttempterAndroid::OnVerifyProgressUpdate(double progress) {
675 assert(status_ == UpdateStatus::VERIFYING);
676 ProgressUpdate(progress);
677 }
678
ScheduleProcessingStart()679 void UpdateAttempterAndroid::ScheduleProcessingStart() {
680 LOG(INFO) << "Scheduling an action processor start.";
681 brillo::MessageLoop::current()->PostTask(
682 FROM_HERE,
683 Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
684 base::Unretained(processor_.get())));
685 }
686
TerminateUpdateAndNotify(ErrorCode error_code)687 void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
688 if (status_ == UpdateStatus::IDLE) {
689 LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called.";
690 return;
691 }
692
693 if (status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE) {
694 LOG(INFO) << "Terminating cleanup previous update.";
695 SetStatusAndNotify(UpdateStatus::IDLE);
696 for (auto observer : daemon_state_->service_observers())
697 observer->SendPayloadApplicationComplete(error_code);
698 return;
699 }
700
701 boot_control_->GetDynamicPartitionControl()->Cleanup();
702
703 download_progress_ = 0;
704 UpdateStatus new_status =
705 (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
706 : UpdateStatus::IDLE);
707 SetStatusAndNotify(new_status);
708 payload_fd_.reset();
709
710 // The network id is only applicable to one download attempt and once it's
711 // done the network id should not be re-used anymore.
712 if (!network_selector_->SetProcessNetwork(kDefaultNetworkId)) {
713 LOG(WARNING) << "Unable to unbind network.";
714 }
715
716 for (auto observer : daemon_state_->service_observers())
717 observer->SendPayloadApplicationComplete(error_code);
718
719 CollectAndReportUpdateMetricsOnUpdateFinished(error_code);
720 ClearMetricsPrefs();
721 if (error_code == ErrorCode::kSuccess) {
722 // We should only reset the PayloadAttemptNumber if the update succeeds, or
723 // we switch to a different payload.
724 prefs_->Delete(kPrefsPayloadAttemptNumber);
725 metrics_utils::SetSystemUpdatedMarker(clock_.get(), prefs_);
726 // Clear the total bytes downloaded if and only if the update succeeds.
727 prefs_->SetInt64(kPrefsTotalBytesDownloaded, 0);
728 }
729 }
730
SetStatusAndNotify(UpdateStatus status)731 void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
732 status_ = status;
733 size_t payload_size =
734 install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size;
735 UpdateEngineStatus status_to_send = {.status = status_,
736 .progress = download_progress_,
737 .new_size_bytes = payload_size};
738
739 for (auto observer : daemon_state_->service_observers()) {
740 observer->SendStatusUpdate(status_to_send);
741 }
742 last_notify_time_ = TimeTicks::Now();
743 }
744
BuildUpdateActions(HttpFetcher * fetcher)745 void UpdateAttempterAndroid::BuildUpdateActions(HttpFetcher* fetcher) {
746 CHECK(!processor_->IsRunning());
747 processor_->set_delegate(this);
748
749 // Actions:
750 auto update_boot_flags_action =
751 std::make_unique<UpdateBootFlagsAction>(boot_control_);
752 auto cleanup_previous_update_action =
753 boot_control_->GetDynamicPartitionControl()
754 ->GetCleanupPreviousUpdateAction(boot_control_, prefs_, this);
755 auto install_plan_action = std::make_unique<InstallPlanAction>(install_plan_);
756 auto download_action =
757 std::make_unique<DownloadAction>(prefs_,
758 boot_control_,
759 hardware_,
760 fetcher, // passes ownership
761 true /* interactive */);
762 download_action->set_delegate(this);
763 download_action->set_base_offset(base_offset_);
764 auto filesystem_verifier_action = std::make_unique<FilesystemVerifierAction>(
765 boot_control_->GetDynamicPartitionControl());
766 auto postinstall_runner_action =
767 std::make_unique<PostinstallRunnerAction>(boot_control_, hardware_);
768 filesystem_verifier_action->set_delegate(this);
769 postinstall_runner_action->set_delegate(this);
770
771 // Bond them together. We have to use the leaf-types when calling
772 // BondActions().
773 BondActions(install_plan_action.get(), download_action.get());
774 BondActions(download_action.get(), filesystem_verifier_action.get());
775 BondActions(filesystem_verifier_action.get(),
776 postinstall_runner_action.get());
777
778 processor_->EnqueueAction(std::move(update_boot_flags_action));
779 processor_->EnqueueAction(std::move(cleanup_previous_update_action));
780 processor_->EnqueueAction(std::move(install_plan_action));
781 processor_->EnqueueAction(std::move(download_action));
782 processor_->EnqueueAction(std::move(filesystem_verifier_action));
783 processor_->EnqueueAction(std::move(postinstall_runner_action));
784 }
785
WriteUpdateCompletedMarker()786 bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
787 string boot_id;
788 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
789 prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id);
790 return true;
791 }
792
UpdateCompletedOnThisBoot()793 bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() {
794 // In case of an update_engine restart without a reboot, we stored the boot_id
795 // when the update was completed by setting a pref, so we can check whether
796 // the last update was on this boot or a previous one.
797 string boot_id;
798 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
799
800 string update_completed_on_boot_id;
801 return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
802 prefs_->GetString(kPrefsUpdateCompletedOnBootId,
803 &update_completed_on_boot_id) &&
804 update_completed_on_boot_id == boot_id);
805 }
806
807 // Collect and report the android metrics when we terminate the update.
CollectAndReportUpdateMetricsOnUpdateFinished(ErrorCode error_code)808 void UpdateAttempterAndroid::CollectAndReportUpdateMetricsOnUpdateFinished(
809 ErrorCode error_code) {
810 int64_t attempt_number =
811 metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
812 PayloadType payload_type = kPayloadTypeFull;
813 int64_t payload_size = 0;
814 for (const auto& p : install_plan_.payloads) {
815 if (p.type == InstallPayloadType::kDelta)
816 payload_type = kPayloadTypeDelta;
817 payload_size += p.size;
818 }
819
820 metrics::AttemptResult attempt_result =
821 metrics_utils::GetAttemptResult(error_code);
822 Time boot_time_start = Time::FromInternalValue(
823 metrics_utils::GetPersistedValue(kPrefsUpdateBootTimestampStart, prefs_));
824 Time monotonic_time_start = Time::FromInternalValue(
825 metrics_utils::GetPersistedValue(kPrefsUpdateTimestampStart, prefs_));
826 TimeDelta duration = clock_->GetBootTime() - boot_time_start;
827 TimeDelta duration_uptime = clock_->GetMonotonicTime() - monotonic_time_start;
828
829 metrics_reporter_->ReportUpdateAttemptMetrics(
830 static_cast<int>(attempt_number),
831 payload_type,
832 duration,
833 duration_uptime,
834 payload_size,
835 attempt_result,
836 error_code);
837
838 int64_t current_bytes_downloaded =
839 metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
840 metrics_reporter_->ReportUpdateAttemptDownloadMetrics(
841 current_bytes_downloaded,
842 0,
843 DownloadSource::kNumDownloadSources,
844 metrics::DownloadErrorCode::kUnset,
845 metrics::ConnectionType::kUnset);
846
847 if (error_code == ErrorCode::kSuccess) {
848 int64_t reboot_count =
849 metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
850 string build_version;
851 prefs_->GetString(kPrefsPreviousVersion, &build_version);
852
853 // For android metrics, we only care about the total bytes downloaded
854 // for all sources; for now we assume the only download source is
855 // HttpsServer.
856 int64_t total_bytes_downloaded =
857 metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
858 int64_t num_bytes_downloaded[kNumDownloadSources] = {};
859 num_bytes_downloaded[DownloadSource::kDownloadSourceHttpsServer] =
860 total_bytes_downloaded;
861
862 int download_overhead_percentage = 0;
863 if (total_bytes_downloaded >= payload_size) {
864 CHECK_GT(payload_size, 0);
865 download_overhead_percentage =
866 (total_bytes_downloaded - payload_size) * 100ull / payload_size;
867 } else {
868 LOG(WARNING) << "Downloaded bytes " << total_bytes_downloaded
869 << " is smaller than the payload size " << payload_size;
870 }
871
872 metrics_reporter_->ReportSuccessfulUpdateMetrics(
873 static_cast<int>(attempt_number),
874 0, // update abandoned count
875 payload_type,
876 payload_size,
877 num_bytes_downloaded,
878 download_overhead_percentage,
879 duration,
880 duration_uptime,
881 static_cast<int>(reboot_count),
882 0); // url_switch_count
883 }
884 }
885
UpdatePrefsAndReportUpdateMetricsOnReboot()886 void UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() {
887 string current_boot_id;
888 TEST_AND_RETURN(utils::GetBootId(¤t_boot_id));
889 // Example: [ro.build.version.incremental]: [4292972]
890 string current_version =
891 android::base::GetProperty("ro.build.version.incremental", "");
892 TEST_AND_RETURN(!current_version.empty());
893 const auto current_slot = boot_control_->GetCurrentSlot();
894
895 // If there's no record of previous version (e.g. due to a data wipe), we
896 // save the info of current boot and skip the metrics report.
897 if (!prefs_->Exists(kPrefsPreviousVersion)) {
898 prefs_->SetString(kPrefsBootId, current_boot_id);
899 prefs_->SetString(kPrefsPreviousVersion, current_version);
900 prefs_->SetInt64(std::string{kPrefsPreviousSlot},
901 boot_control_->GetCurrentSlot());
902 ClearMetricsPrefs();
903 return;
904 }
905 int64_t previous_slot = -1;
906 prefs_->GetInt64(kPrefsPreviousSlot, &previous_slot);
907 string previous_version;
908 // update_engine restarted under the same build and same slot.
909 // TODO(xunchang) identify and report rollback by checking UpdateMarker.
910 if (prefs_->GetString(kPrefsPreviousVersion, &previous_version) &&
911 previous_version == current_version && previous_slot == current_slot) {
912 string last_boot_id;
913 bool is_reboot = prefs_->Exists(kPrefsBootId) &&
914 (prefs_->GetString(kPrefsBootId, &last_boot_id) &&
915 last_boot_id != current_boot_id);
916 // Increment the reboot number if |kPrefsNumReboots| exists. That pref is
917 // set when we start a new update.
918 if (is_reboot && prefs_->Exists(kPrefsNumReboots)) {
919 prefs_->SetString(kPrefsBootId, current_boot_id);
920 int64_t reboot_count =
921 metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
922 metrics_utils::SetNumReboots(reboot_count + 1, prefs_);
923 }
924 return;
925 }
926
927 // Now that the build version changes, report the update metrics.
928 // TODO(xunchang) check the build version is larger than the previous one.
929 prefs_->SetString(kPrefsBootId, current_boot_id);
930 prefs_->SetString(kPrefsPreviousVersion, current_version);
931 prefs_->SetInt64(std::string{kPrefsPreviousSlot},
932 boot_control_->GetCurrentSlot());
933
934 bool previous_attempt_exists = prefs_->Exists(kPrefsPayloadAttemptNumber);
935 // |kPrefsPayloadAttemptNumber| should be cleared upon successful update.
936 if (previous_attempt_exists) {
937 metrics_reporter_->ReportAbnormallyTerminatedUpdateAttemptMetrics();
938 }
939
940 metrics_utils::LoadAndReportTimeToReboot(
941 metrics_reporter_.get(), prefs_, clock_.get());
942 ClearMetricsPrefs();
943
944 // Also reset the update progress if the build version has changed.
945 if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
946 LOG(WARNING) << "Unable to reset the update progress.";
947 }
948 }
949
950 // Save the update start time. Reset the reboot count and attempt number if the
951 // update isn't a resume; otherwise increment the attempt number.
UpdatePrefsOnUpdateStart(bool is_resume)952 void UpdateAttempterAndroid::UpdatePrefsOnUpdateStart(bool is_resume) {
953 if (!is_resume) {
954 metrics_utils::SetNumReboots(0, prefs_);
955 metrics_utils::SetPayloadAttemptNumber(1, prefs_);
956 } else {
957 int64_t attempt_number =
958 metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
959 metrics_utils::SetPayloadAttemptNumber(attempt_number + 1, prefs_);
960 }
961 metrics_utils::SetUpdateTimestampStart(clock_->GetMonotonicTime(), prefs_);
962 metrics_utils::SetUpdateBootTimestampStart(clock_->GetBootTime(), prefs_);
963 }
964
ClearMetricsPrefs()965 void UpdateAttempterAndroid::ClearMetricsPrefs() {
966 CHECK(prefs_);
967 prefs_->Delete(kPrefsCurrentBytesDownloaded);
968 prefs_->Delete(kPrefsNumReboots);
969 prefs_->Delete(kPrefsSystemUpdatedMarker);
970 prefs_->Delete(kPrefsUpdateTimestampStart);
971 prefs_->Delete(kPrefsUpdateBootTimestampStart);
972 }
973
GetCurrentSlot() const974 BootControlInterface::Slot UpdateAttempterAndroid::GetCurrentSlot() const {
975 return boot_control_->GetCurrentSlot();
976 }
977
GetTargetSlot() const978 BootControlInterface::Slot UpdateAttempterAndroid::GetTargetSlot() const {
979 return GetCurrentSlot() == 0 ? 1 : 0;
980 }
981
AllocateSpaceForPayload(const std::string & metadata_filename,const vector<string> & key_value_pair_headers,brillo::ErrorPtr * error)982 uint64_t UpdateAttempterAndroid::AllocateSpaceForPayload(
983 const std::string& metadata_filename,
984 const vector<string>& key_value_pair_headers,
985 brillo::ErrorPtr* error) {
986 DeltaArchiveManifest manifest;
987 if (!VerifyPayloadParseManifest(metadata_filename, &manifest, error)) {
988 return 0;
989 }
990 std::map<string, string> headers;
991 if (!ParseKeyValuePairHeaders(key_value_pair_headers, &headers, error)) {
992 return 0;
993 }
994
995 std::vector<ApexInfo> apex_infos(manifest.apex_info().begin(),
996 manifest.apex_info().end());
997 uint64_t apex_size_required = 0;
998 if (apex_handler_android_ != nullptr) {
999 auto result = apex_handler_android_->CalculateSize(apex_infos);
1000 if (!result.ok()) {
1001 LogAndSetError(error,
1002 FROM_HERE,
1003 "Failed to calculate size required for compressed APEX");
1004 return 0;
1005 }
1006 apex_size_required = *result;
1007 }
1008
1009 string payload_id = GetPayloadId(headers);
1010 uint64_t required_size = 0;
1011 if (!DeltaPerformer::PreparePartitionsForUpdate(prefs_,
1012 boot_control_,
1013 GetTargetSlot(),
1014 manifest,
1015 payload_id,
1016 &required_size)) {
1017 if (required_size == 0) {
1018 LogAndSetError(error, FROM_HERE, "Failed to allocate space for payload.");
1019 return 0;
1020 } else {
1021 LOG(ERROR) << "Insufficient space for payload: " << required_size
1022 << " bytes, apex decompression: " << apex_size_required
1023 << " bytes";
1024 return required_size + apex_size_required;
1025 }
1026 }
1027
1028 if (apex_size_required > 0 && apex_handler_android_ != nullptr &&
1029 !apex_handler_android_->AllocateSpace(apex_infos)) {
1030 LOG(ERROR) << "Insufficient space for apex decompression: "
1031 << apex_size_required << " bytes";
1032 return apex_size_required;
1033 }
1034
1035 LOG(INFO) << "Successfully allocated space for payload.";
1036 return 0;
1037 }
1038
CleanupSuccessfulUpdate(std::unique_ptr<CleanupSuccessfulUpdateCallbackInterface> callback,brillo::ErrorPtr * error)1039 void UpdateAttempterAndroid::CleanupSuccessfulUpdate(
1040 std::unique_ptr<CleanupSuccessfulUpdateCallbackInterface> callback,
1041 brillo::ErrorPtr* error) {
1042 if (cleanup_previous_update_code_.has_value()) {
1043 LOG(INFO) << "CleanupSuccessfulUpdate has previously completed with "
1044 << utils::ErrorCodeToString(*cleanup_previous_update_code_);
1045 if (callback) {
1046 callback->OnCleanupComplete(
1047 static_cast<int32_t>(*cleanup_previous_update_code_));
1048 }
1049 return;
1050 }
1051 if (callback) {
1052 auto callback_ptr = callback.get();
1053 cleanup_previous_update_callbacks_.emplace_back(std::move(callback));
1054 callback_ptr->RegisterForDeathNotifications(
1055 base::Bind(&UpdateAttempterAndroid::RemoveCleanupPreviousUpdateCallback,
1056 base::Unretained(this),
1057 base::Unretained(callback_ptr)));
1058 }
1059 ScheduleCleanupPreviousUpdate();
1060 }
1061
ScheduleCleanupPreviousUpdate()1062 void UpdateAttempterAndroid::ScheduleCleanupPreviousUpdate() {
1063 // If a previous CleanupSuccessfulUpdate call has not finished, or an update
1064 // is in progress, skip enqueueing the action.
1065 if (processor_->IsRunning()) {
1066 LOG(INFO) << "Already processing an update. CleanupPreviousUpdate should "
1067 << "be done when the current update finishes.";
1068 return;
1069 }
1070 LOG(INFO) << "Scheduling CleanupPreviousUpdateAction.";
1071 auto action =
1072 boot_control_->GetDynamicPartitionControl()
1073 ->GetCleanupPreviousUpdateAction(boot_control_, prefs_, this);
1074 processor_->EnqueueAction(std::move(action));
1075 processor_->set_delegate(this);
1076 SetStatusAndNotify(UpdateStatus::CLEANUP_PREVIOUS_UPDATE);
1077 processor_->StartProcessing();
1078 }
1079
OnCleanupProgressUpdate(double progress)1080 void UpdateAttempterAndroid::OnCleanupProgressUpdate(double progress) {
1081 for (auto&& callback : cleanup_previous_update_callbacks_) {
1082 callback->OnCleanupProgressUpdate(progress);
1083 }
1084 }
1085
NotifyCleanupPreviousUpdateCallbacksAndClear()1086 void UpdateAttempterAndroid::NotifyCleanupPreviousUpdateCallbacksAndClear() {
1087 CHECK(cleanup_previous_update_code_.has_value());
1088 for (auto&& callback : cleanup_previous_update_callbacks_) {
1089 callback->OnCleanupComplete(
1090 static_cast<int32_t>(*cleanup_previous_update_code_));
1091 }
1092 cleanup_previous_update_callbacks_.clear();
1093 }
1094
RemoveCleanupPreviousUpdateCallback(CleanupSuccessfulUpdateCallbackInterface * callback)1095 void UpdateAttempterAndroid::RemoveCleanupPreviousUpdateCallback(
1096 CleanupSuccessfulUpdateCallbackInterface* callback) {
1097 auto end_it =
1098 std::remove_if(cleanup_previous_update_callbacks_.begin(),
1099 cleanup_previous_update_callbacks_.end(),
1100 [&](const auto& e) { return e.get() == callback; });
1101 cleanup_previous_update_callbacks_.erase(
1102 end_it, cleanup_previous_update_callbacks_.end());
1103 }
1104
1105 } // namespace chromeos_update_engine
1106