update_attempter_android.cc revision 218397ff42cbef9f1b95fdfe30e8e82145ba9908
15e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo//
25e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// Copyright (C) 2016 The Android Open Source Project
35e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo//
45e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
55e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// you may not use this file except in compliance with the License.
65e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// You may obtain a copy of the License at
75e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo//
85e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
95e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo//
105e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// Unless required by applicable law or agreed to in writing, software
115e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
125e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// See the License for the specific language governing permissions and
145e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// limitations under the License.
155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo//
165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/update_attempter_android.h"
185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <algorithm>
20218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo#include <map>
215e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <utility>
225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
235e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <base/bind.h>
245e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <base/logging.h>
25218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo#include <base/strings/string_number_conversions.h>
265e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <brillo/bind_lambda.h>
275e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <brillo/message_loops/message_loop.h>
28218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo#include <brillo/strings/string_utils.h>
295e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
305e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/common/constants.h"
315e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/common/libcurl_http_fetcher.h"
325e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/common/multi_range_http_fetcher.h"
335e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/common/utils.h"
345e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/daemon_state_android.h"
355e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/payload_consumer/download_action.h"
365e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/payload_consumer/filesystem_verifier_action.h"
375e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/payload_consumer/postinstall_runner_action.h"
385e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
395e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing base::Bind;
405e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing base::TimeDelta;
415e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing base::TimeTicks;
425e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing std::shared_ptr;
435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing std::string;
445e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing std::vector;
455e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymonamespace chromeos_update_engine {
475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
485e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymonamespace {
495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
505e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymoconst char* const kErrorDomain = "update_engine";
515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// TODO(deymo): Convert the different errors to a numeric value to report them
525e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// back on the service error.
535e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymoconst char* const kGenericError = "generic_error";
545e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
555e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// Log and set the error on the passed ErrorPtr.
565e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool LogAndSetError(brillo::ErrorPtr* error,
575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                    const tracked_objects::Location& location,
585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                    const string& reason) {
595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason);
605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  LOG(ERROR) << "Replying with failure: " << location.ToString() << ": "
615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo             << reason;
625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return false;
635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}  // namespace
665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
675e3ea278d9e771be3b51bd72985ad582678baddcAlex DeymoUpdateAttempterAndroid::UpdateAttempterAndroid(
685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    DaemonStateAndroid* daemon_state,
695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    PrefsInterface* prefs,
705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    BootControlInterface* boot_control,
715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    HardwareInterface* hardware)
725e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    : daemon_state_(daemon_state),
735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      prefs_(prefs),
745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      boot_control_(boot_control),
755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      hardware_(hardware),
765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      processor_(new ActionProcessor()) {
775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
795e3ea278d9e771be3b51bd72985ad582678baddcAlex DeymoUpdateAttempterAndroid::~UpdateAttempterAndroid() {
805e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Release ourselves as the ActionProcessor's delegate to prevent
815e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // re-scheduling the updates due to the processing stopped.
825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  processor_->set_delegate(nullptr);
835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
855e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::Init() {
865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // In case of update_engine restart without a reboot we need to restore the
875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // reboot needed state.
885e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (UpdateCompletedOnThisBoot())
895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    status_ = UpdateStatus::UPDATED_NEED_REBOOT;
905e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  else
915e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    status_ = UpdateStatus::IDLE;
925e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
935e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
945e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::ApplyPayload(
955e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    const string& payload_url,
965e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    int64_t payload_offset,
975e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    int64_t payload_size,
985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    const vector<string>& key_value_pair_headers,
995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    brillo::ErrorPtr* error) {
1005e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
1015e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    return LogAndSetError(
1025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo        error, FROM_HERE, "An update already applied, waiting for reboot");
1035e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
1045e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (ongoing_update_) {
1055e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    return LogAndSetError(
1065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo        error, FROM_HERE, "Already processing an update, cancel it first.");
1075e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
1085e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  DCHECK(status_ == UpdateStatus::IDLE);
1095e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
110218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  std::map<string, string> headers;
111218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  for (const string& key_value_pair : key_value_pair_headers) {
112218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    string key;
113218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    string value;
114218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    if (!brillo::string_utils::SplitAtFirst(
115218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo            key_value_pair, "=", &key, &value, false)) {
116218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo      return LogAndSetError(
117218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo          error, FROM_HERE, "Passed invalid header: " + key_value_pair);
118218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    }
119218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    if (!headers.emplace(key, value).second)
120218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo      return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key);
121218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  }
122218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo
123218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  // Unique identifier for the payload. An empty string means that the payload
124218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  // can't be resumed.
125218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  string payload_id = (headers[kPayloadPropertyFileHash] +
126218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo                       headers[kPayloadPropertyMetadataHash]);
1275e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1285e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Setup the InstallPlan based on the request.
1295e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_ = InstallPlan();
1305e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1315e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.download_url = payload_url;
1325e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.version = "";
1330fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo  base_offset_ = payload_offset;
134218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  install_plan_.payload_size = payload_size;
135218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  if (!install_plan_.payload_size) {
136218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    if (!base::StringToUint64(headers[kPayloadPropertyFileSize],
137218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo                              &install_plan_.payload_size)) {
138218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo      install_plan_.payload_size = 0;
139218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    }
140218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  }
141218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  install_plan_.payload_hash = headers[kPayloadPropertyFileHash];
142218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize],
143218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo                            &install_plan_.metadata_size)) {
144218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo    install_plan_.metadata_size = 0;
145218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo  }
1465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.metadata_signature = "";
1475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // The |public_key_rsa| key would override the public key stored on disk.
1485e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.public_key_rsa = "";
1495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1505e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
1515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.is_resume = !payload_id.empty() &&
1525e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                            DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
1535e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (!install_plan_.is_resume) {
1545e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
1555e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      LOG(WARNING) << "Unable to reset the update progress.";
1565e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    }
1575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
1585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      LOG(WARNING) << "Unable to save the update check response hash.";
1595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    }
1605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
1615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // The |is_full_update| is not used anymore since minor_version 3.
1625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.is_full_update = true;
1635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.source_slot = boot_control_->GetCurrentSlot();
1655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
1665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.powerwash_required = false;
1675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  LOG(INFO) << "Using this install plan:";
1695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  install_plan_.Dump();
1705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  BuildUpdateActions();
1725e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  SetupDownload();
1735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  cpu_limiter_.StartLimiter();
1745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
1755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Just in case we didn't update boot flags yet, make sure they're updated
1775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // before any update processing starts. This will start the update process.
1785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  UpdateBootFlags();
1795e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return true;
1805e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
1815e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) {
1835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // TODO(deymo): Implement suspend/resume.
1845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return LogAndSetError(error, FROM_HERE, "Suspend/resume not implemented");
1855e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
1865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) {
1885e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // TODO(deymo): Implement suspend/resume.
1895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return LogAndSetError(error, FROM_HERE, "Suspend/resume not implemented");
1905e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
1915e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1925e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) {
1935e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (status_ == UpdateStatus::IDLE ||
1945e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
1955e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel.");
1965e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
1975e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
1985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // TODO(deymo): Implement cancel.
1995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return LogAndSetError(error, FROM_HERE, "Cancel not implemented");
2005e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2015e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
2035e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                            ErrorCode code) {
2045e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  LOG(INFO) << "Processing Done.";
2055e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (code == ErrorCode::kSuccess) {
2075e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    // Update succeeded.
2085e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    WriteUpdateCompletedMarker();
2095e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
2105e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    DeltaPerformer::ResetUpdateProgress(prefs_, false);
2115e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2125e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    LOG(INFO) << "Update successfully applied, waiting to reboot.";
2135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2145e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  TerminateUpdateAndNotify(code);
2165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ProcessingStopped(
2195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    const ActionProcessor* processor) {
2205e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  TerminateUpdateAndNotify(ErrorCode::kUserCanceled);
2215e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2235e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor,
2245e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                             AbstractAction* action,
2255e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                             ErrorCode code) {
2265e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Reset download progress regardless of whether or not the download
2275e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // action succeeded.
2285e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  const string type = action->Type();
2295e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (type == DownloadAction::StaticType()) {
2305e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    download_progress_ = 0.0;
2315e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2325e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (code != ErrorCode::kSuccess) {
2335e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    // If an action failed, the ActionProcessor will cancel the whole thing.
2345e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    return;
2355e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2365e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (type == DownloadAction::StaticType()) {
2375e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    SetStatusAndNotify(UpdateStatus::FINALIZING);
2385e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2395e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2405e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2415e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed,
2425e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                           uint64_t bytes_received,
2435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                           uint64_t total) {
2445e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  double progress = 0.;
2455e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (total)
2465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    progress = static_cast<double>(bytes_received) / static_cast<double>(total);
2475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Self throttle based on progress. Also send notifications if
2485e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // progress is too slow.
2495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  const double kDeltaPercent = 0.01;  // 1%
2505e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total ||
2515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      progress - download_progress_ >= kDeltaPercent ||
2525e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      TimeTicks::Now() - last_notify_time_ >= TimeDelta::FromSeconds(10)) {
2535e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    download_progress_ = progress;
2545e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    SetStatusAndNotify(UpdateStatus::DOWNLOADING);
2555e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2565e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
2595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // TODO(deymo): Notify the DownloadAction that it should cancel the update
2605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // download.
2615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return false;
2625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::DownloadComplete() {
2655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Nothing needs to be done when the download completes.
2665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::UpdateBootFlags() {
2695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (updated_boot_flags_) {
2705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    LOG(INFO) << "Already updated boot flags. Skipping.";
2715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    CompleteUpdateBootFlags(true);
2725e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    return;
2735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // This is purely best effort.
2755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  LOG(INFO) << "Marking booted slot as good.";
2765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (!boot_control_->MarkBootSuccessfulAsync(
2775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo          Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags,
2785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo               base::Unretained(this)))) {
2795e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    LOG(ERROR) << "Failed to mark current boot as successful.";
2805e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    CompleteUpdateBootFlags(false);
2815e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
2825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) {
2855e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  updated_boot_flags_ = true;
2865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  ScheduleProcessingStart();
2875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2885e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ScheduleProcessingStart() {
2905e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  LOG(INFO) << "Scheduling an action processor start.";
2915e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  brillo::MessageLoop::current()->PostTask(
2925e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      FROM_HERE, Bind([this] { this->processor_->StartProcessing(); }));
2935e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
2945e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
2955e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
2965e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (status_ == UpdateStatus::IDLE) {
2975e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called.";
2985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    return;
2995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
3005e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3015e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Reset cpu shares back to normal.
3025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  cpu_limiter_.StopLimiter();
3035e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  download_progress_ = 0.0;
3045e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  actions_.clear();
3055e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  UpdateStatus new_status =
3065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
3075e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                         : UpdateStatus::IDLE);
3085e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  SetStatusAndNotify(new_status);
3095e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  ongoing_update_ = false;
3105e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3115e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  for (auto observer : daemon_state_->service_observers())
3125e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    observer->SendPayloadApplicationComplete(error_code);
3135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
3145e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
3165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  status_ = status;
3175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  for (auto observer : daemon_state_->service_observers()) {
3185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    observer->SendStatusUpdate(
3195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo        0, download_progress_, status_, "", install_plan_.payload_size);
3205e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
3215e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  last_notify_time_ = TimeTicks::Now();
3225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
3235e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3245e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::BuildUpdateActions() {
3255e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  CHECK(!processor_->IsRunning());
3265e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  processor_->set_delegate(this);
3275e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3285e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Actions:
3295e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  shared_ptr<InstallPlanAction> install_plan_action(
3305e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      new InstallPlanAction(install_plan_));
3315e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3325e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  LibcurlHttpFetcher* download_fetcher =
3335e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
3345e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  download_fetcher->set_server_to_check(ServerToCheck::kDownload);
3355e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  shared_ptr<DownloadAction> download_action(new DownloadAction(
3365e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      prefs_,
3375e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      boot_control_,
3385e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      hardware_,
3395e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      nullptr,                                        // system_state, not used.
3405e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      new MultiRangeHttpFetcher(download_fetcher)));  // passes ownership
3415e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  shared_ptr<FilesystemVerifierAction> dst_filesystem_verifier_action(
3425e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      new FilesystemVerifierAction(boot_control_,
3435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                                   VerifierMode::kVerifyTargetHash));
3445e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3455e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
3465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      new PostinstallRunnerAction(boot_control_));
3475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3485e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  download_action->set_delegate(this);
3495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  download_action_ = download_action;
3505e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
3525e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  actions_.push_back(shared_ptr<AbstractAction>(download_action));
3535e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  actions_.push_back(
3545e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      shared_ptr<AbstractAction>(dst_filesystem_verifier_action));
3555e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
3565e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Bond them together. We have to use the leaf-types when calling
3585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // BondActions().
3595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  BondActions(install_plan_action.get(), download_action.get());
3605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  BondActions(download_action.get(), dst_filesystem_verifier_action.get());
3615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  BondActions(dst_filesystem_verifier_action.get(),
3625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo              postinstall_runner_action.get());
3635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // Enqueue the actions.
3655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  for (const shared_ptr<AbstractAction>& action : actions_)
3665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    processor_->EnqueueAction(action.get());
3675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
3685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
3695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::SetupDownload() {
3705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  MultiRangeHttpFetcher* fetcher =
3715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo      static_cast<MultiRangeHttpFetcher*>(download_action_->http_fetcher());
3725e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  fetcher->ClearRanges();
3735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  if (install_plan_.is_resume) {
3745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    // Resuming an update so fetch the update manifest metadata first.
3755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    int64_t manifest_metadata_size = 0;
3765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    prefs_->GetInt64(kPrefsManifestMetadataSize, &manifest_metadata_size);
3770fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo    fetcher->AddRange(base_offset_, manifest_metadata_size);
3785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    // If there're remaining unprocessed data blobs, fetch them. Be careful not
3795e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    // to request data beyond the end of the payload to avoid 416 HTTP response
3805e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    // error codes.
3815e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    int64_t next_data_offset = 0;
3825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, &next_data_offset);
3835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    uint64_t resume_offset = manifest_metadata_size + next_data_offset;
3840fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo    if (!install_plan_.payload_size) {
3850fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo      fetcher->AddRange(base_offset_ + resume_offset);
3860fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo    } else if (resume_offset < install_plan_.payload_size) {
3870fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo      fetcher->AddRange(base_offset_ + resume_offset,
3880fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo                        install_plan_.payload_size - resume_offset);
3895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo    }
3905e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  } else {
3910fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo    if (install_plan_.payload_size) {
3920fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo      fetcher->AddRange(base_offset_, install_plan_.payload_size);
3930fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo    } else {
3940fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo      // If no payload size is passed we assume we read until the end of the
3950fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo      // stream.
3960fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo      fetcher->AddRange(base_offset_);
3970fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo    }
3985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  }
3995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
4005e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
4015e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
4025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  string boot_id;
4035e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
4045e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id);
4055e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return true;
4065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
4075e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
4085e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() {
4095e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // In case of an update_engine restart without a reboot, we stored the boot_id
4105e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // when the update was completed by setting a pref, so we can check whether
4115e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  // the last update was on this boot or a previous one.
4125e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  string boot_id;
4135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
4145e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
4155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  string update_completed_on_boot_id;
4165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo  return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
4175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo          prefs_->GetString(kPrefsUpdateCompletedOnBootId,
4185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo                            &update_completed_on_boot_id) &&
4195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo          update_completed_on_boot_id == boot_id);
4205e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}
4215e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo
4225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo}  // namespace chromeos_update_engine
423