• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
22 #include <utility>
23 
24 #include <android-base/properties.h>
25 #include <base/bind.h>
26 #include <base/logging.h>
27 #include <base/strings/string_number_conversions.h>
28 #include <brillo/bind_lambda.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/common/constants.h"
35 #include "update_engine/common/error_code_utils.h"
36 #include "update_engine/common/file_fetcher.h"
37 #include "update_engine/common/utils.h"
38 #include "update_engine/daemon_state_interface.h"
39 #include "update_engine/metrics_reporter_interface.h"
40 #include "update_engine/metrics_utils.h"
41 #include "update_engine/network_selector.h"
42 #include "update_engine/payload_consumer/delta_performer.h"
43 #include "update_engine/payload_consumer/download_action.h"
44 #include "update_engine/payload_consumer/file_descriptor.h"
45 #include "update_engine/payload_consumer/file_descriptor_utils.h"
46 #include "update_engine/payload_consumer/filesystem_verifier_action.h"
47 #include "update_engine/payload_consumer/payload_constants.h"
48 #include "update_engine/payload_consumer/payload_metadata.h"
49 #include "update_engine/payload_consumer/postinstall_runner_action.h"
50 #include "update_engine/update_status_utils.h"
51 
52 #ifndef _UE_SIDELOAD
53 // Do not include support for external HTTP(s) urls when building
54 // update_engine_sideload.
55 #include "update_engine/libcurl_http_fetcher.h"
56 #endif
57 
58 using base::Bind;
59 using base::Time;
60 using base::TimeDelta;
61 using base::TimeTicks;
62 using std::shared_ptr;
63 using std::string;
64 using std::vector;
65 using update_engine::UpdateEngineStatus;
66 
67 namespace chromeos_update_engine {
68 
69 namespace {
70 
71 // Minimum threshold to broadcast an status update in progress and time.
72 const double kBroadcastThresholdProgress = 0.01;  // 1%
73 const int kBroadcastThresholdSeconds = 10;
74 
75 const char* const kErrorDomain = "update_engine";
76 // TODO(deymo): Convert the different errors to a numeric value to report them
77 // back on the service error.
78 const char* const kGenericError = "generic_error";
79 
80 // Log and set the error on the passed ErrorPtr.
LogAndSetError(brillo::ErrorPtr * error,const tracked_objects::Location & location,const string & reason)81 bool LogAndSetError(brillo::ErrorPtr* error,
82                     const tracked_objects::Location& location,
83                     const string& reason) {
84   brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason);
85   LOG(ERROR) << "Replying with failure: " << location.ToString() << ": "
86              << reason;
87   return false;
88 }
89 
GetHeaderAsBool(const string & header,bool default_value)90 bool GetHeaderAsBool(const string& header, bool default_value) {
91   int value = 0;
92   if (base::StringToInt(header, &value) && (value == 0 || value == 1))
93     return value == 1;
94   return default_value;
95 }
96 
97 }  // namespace
98 
UpdateAttempterAndroid(DaemonStateInterface * daemon_state,PrefsInterface * prefs,BootControlInterface * boot_control,HardwareInterface * hardware)99 UpdateAttempterAndroid::UpdateAttempterAndroid(
100     DaemonStateInterface* daemon_state,
101     PrefsInterface* prefs,
102     BootControlInterface* boot_control,
103     HardwareInterface* hardware)
104     : daemon_state_(daemon_state),
105       prefs_(prefs),
106       boot_control_(boot_control),
107       hardware_(hardware),
108       processor_(new ActionProcessor()),
109       clock_(new Clock()) {
110   metrics_reporter_ = metrics::CreateMetricsReporter();
111   network_selector_ = network::CreateNetworkSelector();
112 }
113 
~UpdateAttempterAndroid()114 UpdateAttempterAndroid::~UpdateAttempterAndroid() {
115   // Release ourselves as the ActionProcessor's delegate to prevent
116   // re-scheduling the updates due to the processing stopped.
117   processor_->set_delegate(nullptr);
118 }
119 
Init()120 void UpdateAttempterAndroid::Init() {
121   // In case of update_engine restart without a reboot we need to restore the
122   // reboot needed state.
123   if (UpdateCompletedOnThisBoot()) {
124     SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
125   } else {
126     SetStatusAndNotify(UpdateStatus::IDLE);
127     UpdatePrefsAndReportUpdateMetricsOnReboot();
128   }
129 }
130 
ApplyPayload(const string & payload_url,int64_t payload_offset,int64_t payload_size,const vector<string> & key_value_pair_headers,brillo::ErrorPtr * error)131 bool UpdateAttempterAndroid::ApplyPayload(
132     const string& payload_url,
133     int64_t payload_offset,
134     int64_t payload_size,
135     const vector<string>& key_value_pair_headers,
136     brillo::ErrorPtr* error) {
137   if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
138     return LogAndSetError(
139         error, FROM_HERE, "An update already applied, waiting for reboot");
140   }
141   if (ongoing_update_) {
142     return LogAndSetError(
143         error, FROM_HERE, "Already processing an update, cancel it first.");
144   }
145   DCHECK(status_ == UpdateStatus::IDLE);
146 
147   std::map<string, string> headers;
148   for (const string& key_value_pair : key_value_pair_headers) {
149     string key;
150     string value;
151     if (!brillo::string_utils::SplitAtFirst(
152             key_value_pair, "=", &key, &value, false)) {
153       return LogAndSetError(
154           error, FROM_HERE, "Passed invalid header: " + key_value_pair);
155     }
156     if (!headers.emplace(key, value).second)
157       return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key);
158   }
159 
160   // Unique identifier for the payload. An empty string means that the payload
161   // can't be resumed.
162   string payload_id = (headers[kPayloadPropertyFileHash] +
163                        headers[kPayloadPropertyMetadataHash]);
164 
165   // Setup the InstallPlan based on the request.
166   install_plan_ = InstallPlan();
167 
168   install_plan_.download_url = payload_url;
169   install_plan_.version = "";
170   base_offset_ = payload_offset;
171   InstallPlan::Payload payload;
172   payload.size = payload_size;
173   if (!payload.size) {
174     if (!base::StringToUint64(headers[kPayloadPropertyFileSize],
175                               &payload.size)) {
176       payload.size = 0;
177     }
178   }
179   if (!brillo::data_encoding::Base64Decode(headers[kPayloadPropertyFileHash],
180                                            &payload.hash)) {
181     LOG(WARNING) << "Unable to decode base64 file hash: "
182                  << headers[kPayloadPropertyFileHash];
183   }
184   if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize],
185                             &payload.metadata_size)) {
186     payload.metadata_size = 0;
187   }
188   // The |payload.type| is not used anymore since minor_version 3.
189   payload.type = InstallPayloadType::kUnknown;
190   install_plan_.payloads.push_back(payload);
191 
192   // The |public_key_rsa| key would override the public key stored on disk.
193   install_plan_.public_key_rsa = "";
194 
195   install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
196   install_plan_.is_resume = !payload_id.empty() &&
197                             DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
198   if (!install_plan_.is_resume) {
199     if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
200       LOG(WARNING) << "Unable to reset the update progress.";
201     }
202     if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
203       LOG(WARNING) << "Unable to save the update check response hash.";
204     }
205   }
206   install_plan_.source_slot = boot_control_->GetCurrentSlot();
207   install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
208 
209   install_plan_.powerwash_required =
210       GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false);
211 
212   install_plan_.switch_slot_on_reboot =
213       GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true);
214 
215   install_plan_.run_post_install = true;
216   // Optionally skip post install if and only if:
217   // a) we're resuming
218   // b) post install has already succeeded before
219   // c) RUN_POST_INSTALL is set to 0.
220   if (install_plan_.is_resume && prefs_->Exists(kPrefsPostInstallSucceeded)) {
221     bool post_install_succeeded = false;
222     prefs_->GetBoolean(kPrefsPostInstallSucceeded, &post_install_succeeded);
223     if (post_install_succeeded) {
224       install_plan_.run_post_install =
225           GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
226     }
227   }
228 
229   NetworkId network_id = kDefaultNetworkId;
230   if (!headers[kPayloadPropertyNetworkId].empty()) {
231     if (!base::StringToUint64(headers[kPayloadPropertyNetworkId],
232                               &network_id)) {
233       return LogAndSetError(
234           error,
235           FROM_HERE,
236           "Invalid network_id: " + headers[kPayloadPropertyNetworkId]);
237     }
238     if (!network_selector_->SetProcessNetwork(network_id)) {
239       return LogAndSetError(
240           error,
241           FROM_HERE,
242           "Unable to set network_id: " + headers[kPayloadPropertyNetworkId]);
243     }
244   }
245 
246   LOG(INFO) << "Using this install plan:";
247   install_plan_.Dump();
248 
249   BuildUpdateActions(payload_url);
250   // Setup extra headers.
251   HttpFetcher* fetcher = download_action_->http_fetcher();
252   if (!headers[kPayloadPropertyAuthorization].empty())
253     fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]);
254   if (!headers[kPayloadPropertyUserAgent].empty())
255     fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
256 
257   SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
258   ongoing_update_ = true;
259 
260   // Just in case we didn't update boot flags yet, make sure they're updated
261   // before any update processing starts. This will start the update process.
262   UpdateBootFlags();
263 
264   UpdatePrefsOnUpdateStart(install_plan_.is_resume);
265   // TODO(xunchang) report the metrics for unresumable updates
266 
267   return true;
268 }
269 
SuspendUpdate(brillo::ErrorPtr * error)270 bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) {
271   if (!ongoing_update_)
272     return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend.");
273   processor_->SuspendProcessing();
274   return true;
275 }
276 
ResumeUpdate(brillo::ErrorPtr * error)277 bool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) {
278   if (!ongoing_update_)
279     return LogAndSetError(error, FROM_HERE, "No ongoing update to resume.");
280   processor_->ResumeProcessing();
281   return true;
282 }
283 
CancelUpdate(brillo::ErrorPtr * error)284 bool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) {
285   if (!ongoing_update_)
286     return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel.");
287   processor_->StopProcessing();
288   return true;
289 }
290 
ResetStatus(brillo::ErrorPtr * error)291 bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) {
292   LOG(INFO) << "Attempting to reset state from "
293             << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
294 
295   switch (status_) {
296     case UpdateStatus::IDLE:
297       return true;
298 
299     case UpdateStatus::UPDATED_NEED_REBOOT:  {
300       // Remove the reboot marker so that if the machine is rebooted
301       // after resetting to idle state, it doesn't go back to
302       // UpdateStatus::UPDATED_NEED_REBOOT state.
303       bool ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId);
304       ClearMetricsPrefs();
305 
306       // Update the boot flags so the current slot has higher priority.
307       if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot()))
308         ret_value = false;
309 
310       // Mark the current slot as successful again, since marking it as active
311       // may reset the successful bit. We ignore the result of whether marking
312       // the current slot as successful worked.
313       if (!boot_control_->MarkBootSuccessfulAsync(Bind([](bool successful){})))
314         ret_value = false;
315 
316       if (!ret_value) {
317         return LogAndSetError(
318             error,
319             FROM_HERE,
320             "Failed to reset the status to ");
321       }
322 
323       SetStatusAndNotify(UpdateStatus::IDLE);
324       LOG(INFO) << "Reset status successful";
325       return true;
326     }
327 
328     default:
329       return LogAndSetError(
330           error,
331           FROM_HERE,
332           "Reset not allowed in this state. Cancel the ongoing update first");
333   }
334 }
335 
VerifyPayloadApplicable(const std::string & metadata_filename,brillo::ErrorPtr * error)336 bool UpdateAttempterAndroid::VerifyPayloadApplicable(
337     const std::string& metadata_filename, brillo::ErrorPtr* error) {
338   FileDescriptorPtr fd(new EintrSafeFileDescriptor);
339   if (!fd->Open(metadata_filename.c_str(), O_RDONLY)) {
340     return LogAndSetError(
341         error, FROM_HERE, "Failed to open " + metadata_filename);
342   }
343   brillo::Blob metadata(kMaxPayloadHeaderSize);
344   if (!fd->Read(metadata.data(), metadata.size())) {
345     return LogAndSetError(
346         error,
347         FROM_HERE,
348         "Failed to read payload header from " + metadata_filename);
349   }
350   ErrorCode errorcode;
351   PayloadMetadata payload_metadata;
352   if (payload_metadata.ParsePayloadHeader(
353           metadata, kBrilloMajorPayloadVersion, &errorcode) !=
354       MetadataParseResult::kSuccess) {
355     return LogAndSetError(error,
356                           FROM_HERE,
357                           "Failed to parse payload header: " +
358                               utils::ErrorCodeToString(errorcode));
359   }
360   uint64_t metadata_size = payload_metadata.GetMetadataSize() +
361                            payload_metadata.GetMetadataSignatureSize();
362   if (metadata_size < kMaxPayloadHeaderSize ||
363       metadata_size >
364           static_cast<uint64_t>(utils::FileSize(metadata_filename))) {
365     return LogAndSetError(
366         error,
367         FROM_HERE,
368         "Invalid metadata size: " + std::to_string(metadata_size));
369   }
370   metadata.resize(metadata_size);
371   if (!fd->Read(metadata.data() + kMaxPayloadHeaderSize,
372                 metadata.size() - kMaxPayloadHeaderSize)) {
373     return LogAndSetError(
374         error,
375         FROM_HERE,
376         "Failed to read metadata and signature from " + metadata_filename);
377   }
378   fd->Close();
379   errorcode = payload_metadata.ValidateMetadataSignature(
380       metadata, "", base::FilePath(constants::kUpdatePayloadPublicKeyPath));
381   if (errorcode != ErrorCode::kSuccess) {
382     return LogAndSetError(error,
383                           FROM_HERE,
384                           "Failed to validate metadata signature: " +
385                               utils::ErrorCodeToString(errorcode));
386   }
387   DeltaArchiveManifest manifest;
388   if (!payload_metadata.GetManifest(metadata, &manifest)) {
389     return LogAndSetError(error, FROM_HERE, "Failed to parse manifest.");
390   }
391 
392   BootControlInterface::Slot current_slot = boot_control_->GetCurrentSlot();
393   for (const PartitionUpdate& partition : manifest.partitions()) {
394     if (!partition.has_old_partition_info())
395       continue;
396     string partition_path;
397     if (!boot_control_->GetPartitionDevice(
398             partition.partition_name(), current_slot, &partition_path)) {
399       return LogAndSetError(
400           error,
401           FROM_HERE,
402           "Failed to get partition device for " + partition.partition_name());
403     }
404     if (!fd->Open(partition_path.c_str(), O_RDONLY)) {
405       return LogAndSetError(
406           error, FROM_HERE, "Failed to open " + partition_path);
407     }
408     for (const InstallOperation& operation : partition.operations()) {
409       if (!operation.has_src_sha256_hash())
410         continue;
411       brillo::Blob source_hash;
412       if (!fd_utils::ReadAndHashExtents(fd,
413                                         operation.src_extents(),
414                                         manifest.block_size(),
415                                         &source_hash)) {
416         return LogAndSetError(
417             error, FROM_HERE, "Failed to hash " + partition_path);
418       }
419       if (!DeltaPerformer::ValidateSourceHash(
420               source_hash, operation, fd, &errorcode)) {
421         return false;
422       }
423     }
424     fd->Close();
425   }
426   return true;
427 }
428 
ProcessingDone(const ActionProcessor * processor,ErrorCode code)429 void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
430                                             ErrorCode code) {
431   LOG(INFO) << "Processing Done.";
432 
433   switch (code) {
434     case ErrorCode::kSuccess:
435       // Update succeeded.
436       WriteUpdateCompletedMarker();
437       prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
438 
439       LOG(INFO) << "Update successfully applied, waiting to reboot.";
440       break;
441 
442     case ErrorCode::kFilesystemCopierError:
443     case ErrorCode::kNewRootfsVerificationError:
444     case ErrorCode::kNewKernelVerificationError:
445     case ErrorCode::kFilesystemVerifierError:
446     case ErrorCode::kDownloadStateInitializationError:
447       // Reset the ongoing update for these errors so it starts from the
448       // beginning next time.
449       DeltaPerformer::ResetUpdateProgress(prefs_, false);
450       LOG(INFO) << "Resetting update progress.";
451       break;
452 
453     case ErrorCode::kPayloadTimestampError:
454       // SafetyNet logging, b/36232423
455       android_errorWriteLog(0x534e4554, "36232423");
456       break;
457 
458     default:
459       // Ignore all other error codes.
460       break;
461   }
462 
463   TerminateUpdateAndNotify(code);
464 }
465 
ProcessingStopped(const ActionProcessor * processor)466 void UpdateAttempterAndroid::ProcessingStopped(
467     const ActionProcessor* processor) {
468   TerminateUpdateAndNotify(ErrorCode::kUserCanceled);
469 }
470 
ActionCompleted(ActionProcessor * processor,AbstractAction * action,ErrorCode code)471 void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor,
472                                              AbstractAction* action,
473                                              ErrorCode code) {
474   // Reset download progress regardless of whether or not the download
475   // action succeeded.
476   const string type = action->Type();
477   if (type == DownloadAction::StaticType()) {
478     download_progress_ = 0;
479   }
480   if (type == PostinstallRunnerAction::StaticType()) {
481     bool succeeded =
482         code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive;
483     prefs_->SetBoolean(kPrefsPostInstallSucceeded, succeeded);
484   }
485   if (code != ErrorCode::kSuccess) {
486     // If an action failed, the ActionProcessor will cancel the whole thing.
487     return;
488   }
489   if (type == DownloadAction::StaticType()) {
490     SetStatusAndNotify(UpdateStatus::FINALIZING);
491   }
492 }
493 
BytesReceived(uint64_t bytes_progressed,uint64_t bytes_received,uint64_t total)494 void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed,
495                                            uint64_t bytes_received,
496                                            uint64_t total) {
497   double progress = 0;
498   if (total)
499     progress = static_cast<double>(bytes_received) / static_cast<double>(total);
500   if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) {
501     download_progress_ = progress;
502     SetStatusAndNotify(UpdateStatus::DOWNLOADING);
503   } else {
504     ProgressUpdate(progress);
505   }
506 
507   // Update the bytes downloaded in prefs.
508   int64_t current_bytes_downloaded =
509       metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
510   int64_t total_bytes_downloaded =
511       metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
512   prefs_->SetInt64(kPrefsCurrentBytesDownloaded,
513                    current_bytes_downloaded + bytes_progressed);
514   prefs_->SetInt64(kPrefsTotalBytesDownloaded,
515                    total_bytes_downloaded + bytes_progressed);
516 }
517 
ShouldCancel(ErrorCode * cancel_reason)518 bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
519   // TODO(deymo): Notify the DownloadAction that it should cancel the update
520   // download.
521   return false;
522 }
523 
DownloadComplete()524 void UpdateAttempterAndroid::DownloadComplete() {
525   // Nothing needs to be done when the download completes.
526 }
527 
ProgressUpdate(double progress)528 void UpdateAttempterAndroid::ProgressUpdate(double progress) {
529   // Self throttle based on progress. Also send notifications if progress is
530   // too slow.
531   if (progress == 1.0 ||
532       progress - download_progress_ >= kBroadcastThresholdProgress ||
533       TimeTicks::Now() - last_notify_time_ >=
534           TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) {
535     download_progress_ = progress;
536     SetStatusAndNotify(status_);
537   }
538 }
539 
UpdateBootFlags()540 void UpdateAttempterAndroid::UpdateBootFlags() {
541   if (updated_boot_flags_) {
542     LOG(INFO) << "Already updated boot flags. Skipping.";
543     CompleteUpdateBootFlags(true);
544     return;
545   }
546   // This is purely best effort.
547   LOG(INFO) << "Marking booted slot as good.";
548   if (!boot_control_->MarkBootSuccessfulAsync(
549           Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags,
550                base::Unretained(this)))) {
551     LOG(ERROR) << "Failed to mark current boot as successful.";
552     CompleteUpdateBootFlags(false);
553   }
554 }
555 
CompleteUpdateBootFlags(bool successful)556 void UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) {
557   updated_boot_flags_ = true;
558   ScheduleProcessingStart();
559 }
560 
ScheduleProcessingStart()561 void UpdateAttempterAndroid::ScheduleProcessingStart() {
562   LOG(INFO) << "Scheduling an action processor start.";
563   brillo::MessageLoop::current()->PostTask(
564       FROM_HERE,
565       Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
566            base::Unretained(processor_.get())));
567 }
568 
TerminateUpdateAndNotify(ErrorCode error_code)569 void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
570   if (status_ == UpdateStatus::IDLE) {
571     LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called.";
572     return;
573   }
574 
575   download_progress_ = 0;
576   actions_.clear();
577   UpdateStatus new_status =
578       (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
579                                          : UpdateStatus::IDLE);
580   SetStatusAndNotify(new_status);
581   ongoing_update_ = false;
582 
583   // The network id is only applicable to one download attempt and once it's
584   // done the network id should not be re-used anymore.
585   if (!network_selector_->SetProcessNetwork(kDefaultNetworkId)) {
586     LOG(WARNING) << "Unable to unbind network.";
587   }
588 
589   for (auto observer : daemon_state_->service_observers())
590     observer->SendPayloadApplicationComplete(error_code);
591 
592   CollectAndReportUpdateMetricsOnUpdateFinished(error_code);
593   ClearMetricsPrefs();
594   if (error_code == ErrorCode::kSuccess) {
595     metrics_utils::SetSystemUpdatedMarker(clock_.get(), prefs_);
596     // Clear the total bytes downloaded if and only if the update succeeds.
597     prefs_->SetInt64(kPrefsTotalBytesDownloaded, 0);
598   }
599 }
600 
SetStatusAndNotify(UpdateStatus status)601 void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
602   status_ = status;
603   size_t payload_size =
604       install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size;
605   UpdateEngineStatus status_to_send = {.status = status_,
606                                        .progress = download_progress_,
607                                        .new_size_bytes = payload_size};
608 
609   for (auto observer : daemon_state_->service_observers()) {
610     observer->SendStatusUpdate(status_to_send);
611   }
612   last_notify_time_ = TimeTicks::Now();
613 }
614 
BuildUpdateActions(const string & url)615 void UpdateAttempterAndroid::BuildUpdateActions(const string& url) {
616   CHECK(!processor_->IsRunning());
617   processor_->set_delegate(this);
618 
619   // Actions:
620   shared_ptr<InstallPlanAction> install_plan_action(
621       new InstallPlanAction(install_plan_));
622 
623   HttpFetcher* download_fetcher = nullptr;
624   if (FileFetcher::SupportedUrl(url)) {
625     DLOG(INFO) << "Using FileFetcher for file URL.";
626     download_fetcher = new FileFetcher();
627   } else {
628 #ifdef _UE_SIDELOAD
629     LOG(FATAL) << "Unsupported sideload URI: " << url;
630 #else
631     LibcurlHttpFetcher* libcurl_fetcher =
632         new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
633     libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
634     download_fetcher = libcurl_fetcher;
635 #endif  // _UE_SIDELOAD
636   }
637   shared_ptr<DownloadAction> download_action(
638       new DownloadAction(prefs_,
639                          boot_control_,
640                          hardware_,
641                          nullptr,           // system_state, not used.
642                          download_fetcher,  // passes ownership
643                          true /* is_interactive */));
644   shared_ptr<FilesystemVerifierAction> filesystem_verifier_action(
645       new FilesystemVerifierAction());
646 
647   shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
648       new PostinstallRunnerAction(boot_control_, hardware_));
649 
650   download_action->set_delegate(this);
651   download_action->set_base_offset(base_offset_);
652   download_action_ = download_action;
653   postinstall_runner_action->set_delegate(this);
654 
655   actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
656   actions_.push_back(shared_ptr<AbstractAction>(download_action));
657   actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action));
658   actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
659 
660   // Bond them together. We have to use the leaf-types when calling
661   // BondActions().
662   BondActions(install_plan_action.get(), download_action.get());
663   BondActions(download_action.get(), filesystem_verifier_action.get());
664   BondActions(filesystem_verifier_action.get(),
665               postinstall_runner_action.get());
666 
667   // Enqueue the actions.
668   for (const shared_ptr<AbstractAction>& action : actions_)
669     processor_->EnqueueAction(action.get());
670 }
671 
WriteUpdateCompletedMarker()672 bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
673   string boot_id;
674   TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
675   prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id);
676   return true;
677 }
678 
UpdateCompletedOnThisBoot()679 bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() {
680   // In case of an update_engine restart without a reboot, we stored the boot_id
681   // when the update was completed by setting a pref, so we can check whether
682   // the last update was on this boot or a previous one.
683   string boot_id;
684   TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
685 
686   string update_completed_on_boot_id;
687   return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
688           prefs_->GetString(kPrefsUpdateCompletedOnBootId,
689                             &update_completed_on_boot_id) &&
690           update_completed_on_boot_id == boot_id);
691 }
692 
693 // Collect and report the android metrics when we terminate the update.
CollectAndReportUpdateMetricsOnUpdateFinished(ErrorCode error_code)694 void UpdateAttempterAndroid::CollectAndReportUpdateMetricsOnUpdateFinished(
695     ErrorCode error_code) {
696   int64_t attempt_number =
697       metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
698   PayloadType payload_type = kPayloadTypeFull;
699   int64_t payload_size = 0;
700   for (const auto& p : install_plan_.payloads) {
701     if (p.type == InstallPayloadType::kDelta)
702       payload_type = kPayloadTypeDelta;
703     payload_size += p.size;
704   }
705 
706   metrics::AttemptResult attempt_result =
707       metrics_utils::GetAttemptResult(error_code);
708   Time attempt_start_time = Time::FromInternalValue(
709       metrics_utils::GetPersistedValue(kPrefsUpdateTimestampStart, prefs_));
710   TimeDelta duration = clock_->GetBootTime() - attempt_start_time;
711   TimeDelta duration_uptime = clock_->GetMonotonicTime() - attempt_start_time;
712 
713   metrics_reporter_->ReportUpdateAttemptMetrics(
714       nullptr,  // system_state
715       static_cast<int>(attempt_number),
716       payload_type,
717       duration,
718       duration_uptime,
719       payload_size,
720       attempt_result,
721       error_code);
722 
723   int64_t current_bytes_downloaded =
724       metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
725   metrics_reporter_->ReportUpdateAttemptDownloadMetrics(
726       current_bytes_downloaded,
727       0,
728       DownloadSource::kNumDownloadSources,
729       metrics::DownloadErrorCode::kUnset,
730       metrics::ConnectionType::kUnset);
731 
732   if (error_code == ErrorCode::kSuccess) {
733     int64_t reboot_count =
734         metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
735     string build_version;
736     prefs_->GetString(kPrefsPreviousVersion, &build_version);
737 
738     // For android metrics, we only care about the total bytes downloaded
739     // for all sources; for now we assume the only download source is
740     // HttpsServer.
741     int64_t total_bytes_downloaded =
742         metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
743     int64_t num_bytes_downloaded[kNumDownloadSources] = {};
744     num_bytes_downloaded[DownloadSource::kDownloadSourceHttpsServer] =
745         total_bytes_downloaded;
746 
747     int download_overhead_percentage = 0;
748     if (current_bytes_downloaded > 0) {
749       download_overhead_percentage =
750           (total_bytes_downloaded - current_bytes_downloaded) * 100ull /
751           current_bytes_downloaded;
752     }
753     metrics_reporter_->ReportSuccessfulUpdateMetrics(
754         static_cast<int>(attempt_number),
755         0,  // update abandoned count
756         payload_type,
757         payload_size,
758         num_bytes_downloaded,
759         download_overhead_percentage,
760         duration,
761         static_cast<int>(reboot_count),
762         0);  // url_switch_count
763   }
764 }
765 
UpdatePrefsAndReportUpdateMetricsOnReboot()766 void UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() {
767   string current_boot_id;
768   TEST_AND_RETURN(utils::GetBootId(&current_boot_id));
769   // Example: [ro.build.version.incremental]: [4292972]
770   string current_version =
771       android::base::GetProperty("ro.build.version.incremental", "");
772   TEST_AND_RETURN(!current_version.empty());
773 
774   // If there's no record of previous version (e.g. due to a data wipe), we
775   // save the info of current boot and skip the metrics report.
776   if (!prefs_->Exists(kPrefsPreviousVersion)) {
777     prefs_->SetString(kPrefsBootId, current_boot_id);
778     prefs_->SetString(kPrefsPreviousVersion, current_version);
779     ClearMetricsPrefs();
780     return;
781   }
782   string previous_version;
783   // update_engine restarted under the same build.
784   // TODO(xunchang) identify and report rollback by checking UpdateMarker.
785   if (prefs_->GetString(kPrefsPreviousVersion, &previous_version) &&
786       previous_version == current_version) {
787     string last_boot_id;
788     bool is_reboot = prefs_->Exists(kPrefsBootId) &&
789                      (prefs_->GetString(kPrefsBootId, &last_boot_id) &&
790                       last_boot_id != current_boot_id);
791     // Increment the reboot number if |kPrefsNumReboots| exists. That pref is
792     // set when we start a new update.
793     if (is_reboot && prefs_->Exists(kPrefsNumReboots)) {
794       prefs_->SetString(kPrefsBootId, current_boot_id);
795       int64_t reboot_count =
796           metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
797       metrics_utils::SetNumReboots(reboot_count + 1, prefs_);
798     }
799     return;
800   }
801 
802   // Now that the build version changes, report the update metrics.
803   // TODO(xunchang) check the build version is larger than the previous one.
804   prefs_->SetString(kPrefsBootId, current_boot_id);
805   prefs_->SetString(kPrefsPreviousVersion, current_version);
806 
807   bool previous_attempt_exists = prefs_->Exists(kPrefsPayloadAttemptNumber);
808   // |kPrefsPayloadAttemptNumber| should be cleared upon successful update.
809   if (previous_attempt_exists) {
810     metrics_reporter_->ReportAbnormallyTerminatedUpdateAttemptMetrics();
811   }
812 
813   metrics_utils::LoadAndReportTimeToReboot(
814       metrics_reporter_.get(), prefs_, clock_.get());
815   ClearMetricsPrefs();
816 }
817 
818 // Save the update start time. Reset the reboot count and attempt number if the
819 // update isn't a resume; otherwise increment the attempt number.
UpdatePrefsOnUpdateStart(bool is_resume)820 void UpdateAttempterAndroid::UpdatePrefsOnUpdateStart(bool is_resume) {
821   if (!is_resume) {
822     metrics_utils::SetNumReboots(0, prefs_);
823     metrics_utils::SetPayloadAttemptNumber(1, prefs_);
824   } else {
825     int64_t attempt_number =
826         metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
827     metrics_utils::SetPayloadAttemptNumber(attempt_number + 1, prefs_);
828   }
829   Time update_start_time = clock_->GetMonotonicTime();
830   metrics_utils::SetUpdateTimestampStart(update_start_time, prefs_);
831 }
832 
ClearMetricsPrefs()833 void UpdateAttempterAndroid::ClearMetricsPrefs() {
834   CHECK(prefs_);
835   prefs_->Delete(kPrefsCurrentBytesDownloaded);
836   prefs_->Delete(kPrefsNumReboots);
837   prefs_->Delete(kPrefsPayloadAttemptNumber);
838   prefs_->Delete(kPrefsSystemUpdatedMarker);
839   prefs_->Delete(kPrefsUpdateTimestampStart);
840 }
841 
842 }  // namespace chromeos_update_engine
843