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> 2190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu#include <memory> 225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <utility> 235e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu#include <android-base/properties.h> 255e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <base/bind.h> 265e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <base/logging.h> 27218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo#include <base/strings/string_number_conversions.h> 285e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <brillo/bind_lambda.h> 292703ef4466066d64d8021904e233b120f38c0272Sen Jiang#include <brillo/data_encoding.h> 305e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include <brillo/message_loops/message_loop.h> 31218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo#include <brillo/strings/string_utils.h> 32acbdd1cc442e80df4ca35ba27fdeed1c8b00f5c1Sen Jiang#include <log/log_safetynet.h> 335e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 345e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/common/constants.h" 358371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang#include "update_engine/common/error_code_utils.h" 362c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo#include "update_engine/common/file_fetcher.h" 375e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/common/utils.h" 3803a4de7dc77b058987fc0670f4f67ba10ff31bc8Alex Deymo#include "update_engine/daemon_state_interface.h" 39d4c5debc65bb35ee61c2764bda059b7f307fd093Tianjie Xu#include "update_engine/metrics_reporter_interface.h" 401b66114d367d1b85b4397bb559e274dbd0ebcd31Tianjie Xu#include "update_engine/metrics_utils.h" 4187792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo#include "update_engine/network_selector.h" 428371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang#include "update_engine/payload_consumer/delta_performer.h" 435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/payload_consumer/download_action.h" 448371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang#include "update_engine/payload_consumer/file_descriptor.h" 458371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang#include "update_engine/payload_consumer/file_descriptor_utils.h" 465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/payload_consumer/filesystem_verifier_action.h" 478371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang#include "update_engine/payload_consumer/payload_constants.h" 488371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang#include "update_engine/payload_consumer/payload_metadata.h" 495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo#include "update_engine/payload_consumer/postinstall_runner_action.h" 503b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo#include "update_engine/update_status_utils.h" 515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5214c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo#ifndef _UE_SIDELOAD 5314c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo// Do not include support for external HTTP(s) urls when building 5414c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo// update_engine_sideload. 5514c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo#include "update_engine/libcurl_http_fetcher.h" 5614c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo#endif 5714c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo 585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing base::Bind; 5990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xuusing base::Time; 605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing base::TimeDelta; 615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing base::TimeTicks; 625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing std::shared_ptr; 635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing std::string; 645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymousing std::vector; 657f92e2b7060cb35719acf96ef96a4e273e165bc5Aaron Woodusing update_engine::UpdateEngineStatus; 665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymonamespace chromeos_update_engine { 685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymonamespace { 705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 710d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo// Minimum threshold to broadcast an status update in progress and time. 720d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymoconst double kBroadcastThresholdProgress = 0.01; // 1% 730d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymoconst int kBroadcastThresholdSeconds = 10; 740d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymoconst char* const kErrorDomain = "update_engine"; 765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// TODO(deymo): Convert the different errors to a numeric value to report them 775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// back on the service error. 785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymoconst char* const kGenericError = "generic_error"; 795e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 805e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo// Log and set the error on the passed ErrorPtr. 815e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool LogAndSetError(brillo::ErrorPtr* error, 825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo const tracked_objects::Location& location, 835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo const string& reason) { 845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason); 855e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(ERROR) << "Replying with failure: " << location.ToString() << ": " 865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo << reason; 875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return false; 885e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 90fe5228282571154b51d3907cad4744e228e66a22Sen Jiangbool GetHeaderAsBool(const string& header, bool default_value) { 91fe5228282571154b51d3907cad4744e228e66a22Sen Jiang int value = 0; 92fe5228282571154b51d3907cad4744e228e66a22Sen Jiang if (base::StringToInt(header, &value) && (value == 0 || value == 1)) 93fe5228282571154b51d3907cad4744e228e66a22Sen Jiang return value == 1; 94fe5228282571154b51d3907cad4744e228e66a22Sen Jiang return default_value; 95fe5228282571154b51d3907cad4744e228e66a22Sen Jiang} 96fe5228282571154b51d3907cad4744e228e66a22Sen Jiang 975e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} // namespace 985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 995e3ea278d9e771be3b51bd72985ad582678baddcAlex DeymoUpdateAttempterAndroid::UpdateAttempterAndroid( 10003a4de7dc77b058987fc0670f4f67ba10ff31bc8Alex Deymo DaemonStateInterface* daemon_state, 1015e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo PrefsInterface* prefs, 1025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo BootControlInterface* boot_control, 1035e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo HardwareInterface* hardware) 1045e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo : daemon_state_(daemon_state), 1055e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo prefs_(prefs), 1065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo boot_control_(boot_control), 1075e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo hardware_(hardware), 1081b66114d367d1b85b4397bb559e274dbd0ebcd31Tianjie Xu processor_(new ActionProcessor()), 109d4c5debc65bb35ee61c2764bda059b7f307fd093Tianjie Xu clock_(new Clock()) { 110d4c5debc65bb35ee61c2764bda059b7f307fd093Tianjie Xu metrics_reporter_ = metrics::CreateMetricsReporter(); 11187792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo network_selector_ = network::CreateNetworkSelector(); 1125e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 1135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 1145e3ea278d9e771be3b51bd72985ad582678baddcAlex DeymoUpdateAttempterAndroid::~UpdateAttempterAndroid() { 1155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Release ourselves as the ActionProcessor's delegate to prevent 1165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // re-scheduling the updates due to the processing stopped. 1175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo processor_->set_delegate(nullptr); 1185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 1195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 1205e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::Init() { 1215e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // In case of update_engine restart without a reboot we need to restore the 1225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // reboot needed state. 12390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (UpdateCompletedOnThisBoot()) { 1240e061aebc651e041b6d1d8a3a91834feb87e0d62Alex Deymo SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT); 12590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } else { 1260e061aebc651e041b6d1d8a3a91834feb87e0d62Alex Deymo SetStatusAndNotify(UpdateStatus::IDLE); 12790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu UpdatePrefsAndReportUpdateMetricsOnReboot(); 12890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 1295e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 1305e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 1315e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::ApplyPayload( 1325e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo const string& payload_url, 1335e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo int64_t payload_offset, 1345e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo int64_t payload_size, 1355e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo const vector<string>& key_value_pair_headers, 1365e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo brillo::ErrorPtr* error) { 1375e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) { 1385e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return LogAndSetError( 1395e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo error, FROM_HERE, "An update already applied, waiting for reboot"); 1405e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 1415e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (ongoing_update_) { 1425e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return LogAndSetError( 1435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo error, FROM_HERE, "Already processing an update, cancel it first."); 1445e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 1455e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo DCHECK(status_ == UpdateStatus::IDLE); 1465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 147218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo std::map<string, string> headers; 148218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo for (const string& key_value_pair : key_value_pair_headers) { 149218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo string key; 150218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo string value; 151218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo if (!brillo::string_utils::SplitAtFirst( 152218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo key_value_pair, "=", &key, &value, false)) { 153218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo return LogAndSetError( 154218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo error, FROM_HERE, "Passed invalid header: " + key_value_pair); 155218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo } 156218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo if (!headers.emplace(key, value).second) 157218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key); 158218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo } 159218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo 160218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo // Unique identifier for the payload. An empty string means that the payload 161218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo // can't be resumed. 162218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo string payload_id = (headers[kPayloadPropertyFileHash] + 163218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo headers[kPayloadPropertyMetadataHash]); 1645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 1655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Setup the InstallPlan based on the request. 1665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_ = InstallPlan(); 1675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 1685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.download_url = payload_url; 1695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.version = ""; 1700fd51ff8fd200aab7f9ab930b47736505a7b59c3Alex Deymo base_offset_ = payload_offset; 1710affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang InstallPlan::Payload payload; 1720affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang payload.size = payload_size; 1730affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang if (!payload.size) { 174218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo if (!base::StringToUint64(headers[kPayloadPropertyFileSize], 1750affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang &payload.size)) { 1760affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang payload.size = 0; 177218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo } 178218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo } 1792703ef4466066d64d8021904e233b120f38c0272Sen Jiang if (!brillo::data_encoding::Base64Decode(headers[kPayloadPropertyFileHash], 1800affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang &payload.hash)) { 1812703ef4466066d64d8021904e233b120f38c0272Sen Jiang LOG(WARNING) << "Unable to decode base64 file hash: " 1822703ef4466066d64d8021904e233b120f38c0272Sen Jiang << headers[kPayloadPropertyFileHash]; 1832703ef4466066d64d8021904e233b120f38c0272Sen Jiang } 184218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize], 1850affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang &payload.metadata_size)) { 1860affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang payload.metadata_size = 0; 187218397ff42cbef9f1b95fdfe30e8e82145ba9908Alex Deymo } 188cdd5206c6507fa5c70344c269053d30777f7d674Sen Jiang // The |payload.type| is not used anymore since minor_version 3. 189cdd5206c6507fa5c70344c269053d30777f7d674Sen Jiang payload.type = InstallPayloadType::kUnknown; 1900affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang install_plan_.payloads.push_back(payload); 1910affc2c099fac47b999ba39f8f1bacb418e65a97Sen Jiang 1925e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // The |public_key_rsa| key would override the public key stored on disk. 1935e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.public_key_rsa = ""; 1945e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 1955e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild(); 1965e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.is_resume = !payload_id.empty() && 1975e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo DeltaPerformer::CanResumeUpdate(prefs_, payload_id); 1985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (!install_plan_.is_resume) { 1995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) { 2005e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(WARNING) << "Unable to reset the update progress."; 2015e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 2025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) { 2035e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(WARNING) << "Unable to save the update check response hash."; 2045e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 2055e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 2065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.source_slot = boot_control_->GetCurrentSlot(); 2075e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0; 208fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo 209fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo install_plan_.powerwash_required = 210fe5228282571154b51d3907cad4744e228e66a22Sen Jiang GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false); 211fe5228282571154b51d3907cad4744e228e66a22Sen Jiang 212fe5228282571154b51d3907cad4744e228e66a22Sen Jiang install_plan_.switch_slot_on_reboot = 213fe5228282571154b51d3907cad4744e228e66a22Sen Jiang GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true); 214fe5228282571154b51d3907cad4744e228e66a22Sen Jiang 215fe5228282571154b51d3907cad4744e228e66a22Sen Jiang install_plan_.run_post_install = true; 216fe5228282571154b51d3907cad4744e228e66a22Sen Jiang // Optionally skip post install if and only if: 217fe5228282571154b51d3907cad4744e228e66a22Sen Jiang // a) we're resuming 218fe5228282571154b51d3907cad4744e228e66a22Sen Jiang // b) post install has already succeeded before 219fe5228282571154b51d3907cad4744e228e66a22Sen Jiang // c) RUN_POST_INSTALL is set to 0. 220fe5228282571154b51d3907cad4744e228e66a22Sen Jiang if (install_plan_.is_resume && prefs_->Exists(kPrefsPostInstallSucceeded)) { 221fe5228282571154b51d3907cad4744e228e66a22Sen Jiang bool post_install_succeeded = false; 222fe5228282571154b51d3907cad4744e228e66a22Sen Jiang prefs_->GetBoolean(kPrefsPostInstallSucceeded, &post_install_succeeded); 223fe5228282571154b51d3907cad4744e228e66a22Sen Jiang if (post_install_succeeded) { 224fe5228282571154b51d3907cad4744e228e66a22Sen Jiang install_plan_.run_post_install = 225fe5228282571154b51d3907cad4744e228e66a22Sen Jiang GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true); 226fe5228282571154b51d3907cad4744e228e66a22Sen Jiang } 227fe5228282571154b51d3907cad4744e228e66a22Sen Jiang } 2285e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 22987792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo NetworkId network_id = kDefaultNetworkId; 23087792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo if (!headers[kPayloadPropertyNetworkId].empty()) { 23187792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo if (!base::StringToUint64(headers[kPayloadPropertyNetworkId], 23287792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo &network_id)) { 23387792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo return LogAndSetError( 23487792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo error, 23587792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo FROM_HERE, 23687792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo "Invalid network_id: " + headers[kPayloadPropertyNetworkId]); 23787792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo } 23887792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo if (!network_selector_->SetProcessNetwork(network_id)) { 239cbd37c68ca69ceec25a9609c0c36fa30ee707f6dSen Jiang return LogAndSetError( 240cbd37c68ca69ceec25a9609c0c36fa30ee707f6dSen Jiang error, 241cbd37c68ca69ceec25a9609c0c36fa30ee707f6dSen Jiang FROM_HERE, 242cbd37c68ca69ceec25a9609c0c36fa30ee707f6dSen Jiang "Unable to set network_id: " + headers[kPayloadPropertyNetworkId]); 24387792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo } 24487792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo } 24587792ea818a63f2d246bbba2b7429b85ee8d669fAlex Deymo 2465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(INFO) << "Using this install plan:"; 2475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo install_plan_.Dump(); 2485e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2492c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo BuildUpdateActions(payload_url); 250fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo // Setup extra headers. 251fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo HttpFetcher* fetcher = download_action_->http_fetcher(); 252fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo if (!headers[kPayloadPropertyAuthorization].empty()) 253fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]); 254fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo if (!headers[kPayloadPropertyUserAgent].empty()) 255fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]); 256fdd6dec9c4be2fbd667cf874c4cc6f4ffecaeef9Alex Deymo 2575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE); 258f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo ongoing_update_ = true; 2595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Just in case we didn't update boot flags yet, make sure they're updated 2615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // before any update processing starts. This will start the update process. 2625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo UpdateBootFlags(); 26390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 26490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu UpdatePrefsOnUpdateStart(install_plan_.is_resume); 26590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // TODO(xunchang) report the metrics for unresumable updates 26690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 2675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return true; 2685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 2695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) { 271f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo if (!ongoing_update_) 272f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend."); 273f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo processor_->SuspendProcessing(); 274f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo return true; 2755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 2765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) { 278f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo if (!ongoing_update_) 279f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo return LogAndSetError(error, FROM_HERE, "No ongoing update to resume."); 280f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo processor_->ResumeProcessing(); 281f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo return true; 2825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 2835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) { 285f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo if (!ongoing_update_) 2865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel."); 287f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo processor_->StopProcessing(); 288f28585764e91b7c25a7c2856ff645c8bb22d64a9Alex Deymo return true; 2895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 2905e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 2913b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymobool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) { 2923b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo LOG(INFO) << "Attempting to reset state from " 2933b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo << UpdateStatusToString(status_) << " to UpdateStatus::IDLE"; 2943b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 2953b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo switch (status_) { 2963b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo case UpdateStatus::IDLE: 2973b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo return true; 2983b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 2993b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo case UpdateStatus::UPDATED_NEED_REBOOT: { 3003b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo // Remove the reboot marker so that if the machine is rebooted 3013b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo // after resetting to idle state, it doesn't go back to 3023b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo // UpdateStatus::UPDATED_NEED_REBOOT state. 3033b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo bool ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId); 30490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu ClearMetricsPrefs(); 3053b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 3063b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo // Update the boot flags so the current slot has higher priority. 3073b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot())) 3083b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo ret_value = false; 3093b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 3105259033d23938ce3ce20e4a9b599be0eec113610Alex Deymo // Mark the current slot as successful again, since marking it as active 3115259033d23938ce3ce20e4a9b599be0eec113610Alex Deymo // may reset the successful bit. We ignore the result of whether marking 3125259033d23938ce3ce20e4a9b599be0eec113610Alex Deymo // the current slot as successful worked. 3135259033d23938ce3ce20e4a9b599be0eec113610Alex Deymo if (!boot_control_->MarkBootSuccessfulAsync(Bind([](bool successful){}))) 3145259033d23938ce3ce20e4a9b599be0eec113610Alex Deymo ret_value = false; 3155259033d23938ce3ce20e4a9b599be0eec113610Alex Deymo 3163b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo if (!ret_value) { 3173b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo return LogAndSetError( 3183b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo error, 3193b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo FROM_HERE, 3203b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo "Failed to reset the status to "); 3213b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo } 3223b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 3233b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo SetStatusAndNotify(UpdateStatus::IDLE); 3243b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo LOG(INFO) << "Reset status successful"; 3253b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo return true; 3263b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo } 3273b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 3283b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo default: 3293b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo return LogAndSetError( 3303b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo error, 3313b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo FROM_HERE, 3323b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo "Reset not allowed in this state. Cancel the ongoing update first"); 3333b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo } 3343b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo} 3353b678db2e7fd4baa38c6d6b8bb8334f7d88b8682Alex Deymo 3368371c1c852eae461043d8a3d911394a0ec0db909Sen Jiangbool UpdateAttempterAndroid::VerifyPayloadApplicable( 3378371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang const std::string& metadata_filename, brillo::ErrorPtr* error) { 3388371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FileDescriptorPtr fd(new EintrSafeFileDescriptor); 3398371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!fd->Open(metadata_filename.c_str(), O_RDONLY)) { 3408371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 3418371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, FROM_HERE, "Failed to open " + metadata_filename); 3428371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3438371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang brillo::Blob metadata(kMaxPayloadHeaderSize); 3448371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!fd->Read(metadata.data(), metadata.size())) { 3458371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 3468371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, 3478371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FROM_HERE, 3488371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang "Failed to read payload header from " + metadata_filename); 3498371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3508371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang ErrorCode errorcode; 3518371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang PayloadMetadata payload_metadata; 3528371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (payload_metadata.ParsePayloadHeader( 3538371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang metadata, kBrilloMajorPayloadVersion, &errorcode) != 3548371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang MetadataParseResult::kSuccess) { 3558371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError(error, 3568371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FROM_HERE, 3578371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang "Failed to parse payload header: " + 3588371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang utils::ErrorCodeToString(errorcode)); 3598371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3608371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang metadata.resize(payload_metadata.GetMetadataSize() + 3618371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang payload_metadata.GetMetadataSignatureSize()); 3628371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (metadata.size() < kMaxPayloadHeaderSize) { 3638371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 3648371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, 3658371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FROM_HERE, 3668371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang "Metadata size too small: " + std::to_string(metadata.size())); 3678371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3688371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!fd->Read(metadata.data() + kMaxPayloadHeaderSize, 3698371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang metadata.size() - kMaxPayloadHeaderSize)) { 3708371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 3718371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, 3728371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FROM_HERE, 3738371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang "Failed to read metadata and signature from " + metadata_filename); 3748371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3758371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang fd->Close(); 3768371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang errorcode = payload_metadata.ValidateMetadataSignature( 3778371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang metadata, "", base::FilePath(constants::kUpdatePayloadPublicKeyPath)); 3788371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (errorcode != ErrorCode::kSuccess) { 3798371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError(error, 3808371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FROM_HERE, 3818371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang "Failed to validate metadata signature: " + 3828371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang utils::ErrorCodeToString(errorcode)); 3838371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3848371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang DeltaArchiveManifest manifest; 3858371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!payload_metadata.GetManifest(metadata, &manifest)) { 3868371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError(error, FROM_HERE, "Failed to parse manifest."); 3878371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 3888371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang 3898371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang BootControlInterface::Slot current_slot = boot_control_->GetCurrentSlot(); 3908371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang for (const PartitionUpdate& partition : manifest.partitions()) { 3918371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!partition.has_old_partition_info()) 3928371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang continue; 3938371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang string partition_path; 3948371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!boot_control_->GetPartitionDevice( 3958371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang partition.partition_name(), current_slot, &partition_path)) { 3968371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 3978371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, 3988371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang FROM_HERE, 3998371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang "Failed to get partition device for " + partition.partition_name()); 4008371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 4018371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!fd->Open(partition_path.c_str(), O_RDONLY)) { 4028371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 4038371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, FROM_HERE, "Failed to open " + partition_path); 4048371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 4058371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang for (const InstallOperation& operation : partition.operations()) { 4068371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!operation.has_src_sha256_hash()) 4078371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang continue; 4088371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang brillo::Blob source_hash; 4098371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!fd_utils::ReadAndHashExtents(fd, 4108371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang operation.src_extents(), 4118371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang manifest.block_size(), 4128371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang &source_hash)) { 4138371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return LogAndSetError( 4148371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang error, FROM_HERE, "Failed to hash " + partition_path); 4158371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 4168371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang if (!DeltaPerformer::ValidateSourceHash( 4178371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang source_hash, operation, fd, &errorcode)) { 4188371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return false; 4198371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 4208371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 4218371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang fd->Close(); 4228371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang } 4238371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang return true; 4248371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang} 4258371c1c852eae461043d8a3d911394a0ec0db909Sen Jiang 4265e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor, 4275e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo ErrorCode code) { 4285e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(INFO) << "Processing Done."; 4295e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 4305990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo switch (code) { 4315990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo case ErrorCode::kSuccess: 4325990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo // Update succeeded. 4335990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo WriteUpdateCompletedMarker(); 4345990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0); 4355990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo 4365990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo LOG(INFO) << "Update successfully applied, waiting to reboot."; 4375990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo break; 4385990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo 4395990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo case ErrorCode::kFilesystemCopierError: 4405990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo case ErrorCode::kNewRootfsVerificationError: 4415990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo case ErrorCode::kNewKernelVerificationError: 4425990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo case ErrorCode::kFilesystemVerifierError: 4435990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo case ErrorCode::kDownloadStateInitializationError: 4445990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo // Reset the ongoing update for these errors so it starts from the 4455990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo // beginning next time. 4465990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo DeltaPerformer::ResetUpdateProgress(prefs_, false); 4475990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo LOG(INFO) << "Resetting update progress."; 4485990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo break; 4495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 450acbdd1cc442e80df4ca35ba27fdeed1c8b00f5c1Sen Jiang case ErrorCode::kPayloadTimestampError: 451acbdd1cc442e80df4ca35ba27fdeed1c8b00f5c1Sen Jiang // SafetyNet logging, b/36232423 452acbdd1cc442e80df4ca35ba27fdeed1c8b00f5c1Sen Jiang android_errorWriteLog(0x534e4554, "36232423"); 453acbdd1cc442e80df4ca35ba27fdeed1c8b00f5c1Sen Jiang break; 454acbdd1cc442e80df4ca35ba27fdeed1c8b00f5c1Sen Jiang 4555990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo default: 4565990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo // Ignore all other error codes. 4575990bf33b50beec0caf55a97f5ca87608ccbc694Alex Deymo break; 45803a4de7dc77b058987fc0670f4f67ba10ff31bc8Alex Deymo } 4595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 4605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo TerminateUpdateAndNotify(code); 4615e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 4625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 4635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ProcessingStopped( 4645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo const ActionProcessor* processor) { 4655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo TerminateUpdateAndNotify(ErrorCode::kUserCanceled); 4665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 4675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 4685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor, 4695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo AbstractAction* action, 4705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo ErrorCode code) { 4715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Reset download progress regardless of whether or not the download 4725e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // action succeeded. 4735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo const string type = action->Type(); 4745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (type == DownloadAction::StaticType()) { 4750d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo download_progress_ = 0; 4765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 477fe5228282571154b51d3907cad4744e228e66a22Sen Jiang if (type == PostinstallRunnerAction::StaticType()) { 478fe5228282571154b51d3907cad4744e228e66a22Sen Jiang bool succeeded = 479fe5228282571154b51d3907cad4744e228e66a22Sen Jiang code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive; 480fe5228282571154b51d3907cad4744e228e66a22Sen Jiang prefs_->SetBoolean(kPrefsPostInstallSucceeded, succeeded); 481fe5228282571154b51d3907cad4744e228e66a22Sen Jiang } 4825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (code != ErrorCode::kSuccess) { 4835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // If an action failed, the ActionProcessor will cancel the whole thing. 4845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return; 4855e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 4865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (type == DownloadAction::StaticType()) { 4875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo SetStatusAndNotify(UpdateStatus::FINALIZING); 4885e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 4895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 4905e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 4915e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed, 4925e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo uint64_t bytes_received, 4935e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo uint64_t total) { 4940d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo double progress = 0; 4955e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (total) 4965e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo progress = static_cast<double>(bytes_received) / static_cast<double>(total); 4970d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) { 4985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo download_progress_ = progress; 4995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo SetStatusAndNotify(UpdateStatus::DOWNLOADING); 5000d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo } else { 5010d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo ProgressUpdate(progress); 5025e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 503d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu 504d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu // Update the bytes downloaded in prefs. 505d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu int64_t current_bytes_downloaded = 506d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_); 507d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu int64_t total_bytes_downloaded = 508d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_); 509d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu prefs_->SetInt64(kPrefsCurrentBytesDownloaded, 510d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu current_bytes_downloaded + bytes_progressed); 511d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu prefs_->SetInt64(kPrefsTotalBytesDownloaded, 512d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu total_bytes_downloaded + bytes_progressed); 5135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5145e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) { 5165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // TODO(deymo): Notify the DownloadAction that it should cancel the update 5175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // download. 5185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return false; 5195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5205e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5215e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::DownloadComplete() { 5225e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Nothing needs to be done when the download completes. 5235e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5245e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5250d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymovoid UpdateAttempterAndroid::ProgressUpdate(double progress) { 5260d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo // Self throttle based on progress. Also send notifications if progress is 5270d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo // too slow. 5280d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo if (progress == 1.0 || 5290d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo progress - download_progress_ >= kBroadcastThresholdProgress || 5300d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo TimeTicks::Now() - last_notify_time_ >= 5310d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) { 5320d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo download_progress_ = progress; 5330d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo SetStatusAndNotify(status_); 5340d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo } 5350d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo} 5360d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 5375e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::UpdateBootFlags() { 5385e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (updated_boot_flags_) { 5395e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(INFO) << "Already updated boot flags. Skipping."; 5405e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo CompleteUpdateBootFlags(true); 5415e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return; 5425e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 5435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // This is purely best effort. 5445e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(INFO) << "Marking booted slot as good."; 5455e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (!boot_control_->MarkBootSuccessfulAsync( 5465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags, 5475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo base::Unretained(this)))) { 5485e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(ERROR) << "Failed to mark current boot as successful."; 5495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo CompleteUpdateBootFlags(false); 5505e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 5515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5525e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5535e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) { 5545e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo updated_boot_flags_ = true; 5555e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo ScheduleProcessingStart(); 5565e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::ScheduleProcessingStart() { 5595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(INFO) << "Scheduling an action processor start."; 5605e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo brillo::MessageLoop::current()->PostTask( 561f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez FROM_HERE, 562f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez Bind([](ActionProcessor* processor) { processor->StartProcessing(); }, 563f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez base::Unretained(processor_.get()))); 5645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) { 5675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo if (status_ == UpdateStatus::IDLE) { 5685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called."; 5695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return; 5705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 5715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5720d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo download_progress_ = 0; 5735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo actions_.clear(); 5745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo UpdateStatus new_status = 5755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT 5765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo : UpdateStatus::IDLE); 5775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo SetStatusAndNotify(new_status); 5785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo ongoing_update_ = false; 5795e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 580b19c3ec7bda83b15c7fc659f65eb6f92ca84f9c4Sen Jiang // The network id is only applicable to one download attempt and once it's 581b19c3ec7bda83b15c7fc659f65eb6f92ca84f9c4Sen Jiang // done the network id should not be re-used anymore. 582b19c3ec7bda83b15c7fc659f65eb6f92ca84f9c4Sen Jiang if (!network_selector_->SetProcessNetwork(kDefaultNetworkId)) { 583b19c3ec7bda83b15c7fc659f65eb6f92ca84f9c4Sen Jiang LOG(WARNING) << "Unable to unbind network."; 584b19c3ec7bda83b15c7fc659f65eb6f92ca84f9c4Sen Jiang } 585b19c3ec7bda83b15c7fc659f65eb6f92ca84f9c4Sen Jiang 5865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo for (auto observer : daemon_state_->service_observers()) 5875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo observer->SendPayloadApplicationComplete(error_code); 5881b66114d367d1b85b4397bb559e274dbd0ebcd31Tianjie Xu 58990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu CollectAndReportUpdateMetricsOnUpdateFinished(error_code); 59090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu ClearMetricsPrefs(); 59190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (error_code == ErrorCode::kSuccess) { 59290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::SetSystemUpdatedMarker(clock_.get(), prefs_); 593d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu // Clear the total bytes downloaded if and only if the update succeeds. 594d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu prefs_->SetInt64(kPrefsTotalBytesDownloaded, 0); 59590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 5965e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 5975e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 5985e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymovoid UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) { 5995e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo status_ = status; 6002d1c87bbd55878c5b4dd93e97a8cc28e715137ecSen Jiang size_t payload_size = 6012d1c87bbd55878c5b4dd93e97a8cc28e715137ecSen Jiang install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size; 6027f92e2b7060cb35719acf96ef96a4e273e165bc5Aaron Wood UpdateEngineStatus status_to_send = {.status = status_, 6037f92e2b7060cb35719acf96ef96a4e273e165bc5Aaron Wood .progress = download_progress_, 6047f92e2b7060cb35719acf96ef96a4e273e165bc5Aaron Wood .new_size_bytes = payload_size}; 6057f92e2b7060cb35719acf96ef96a4e273e165bc5Aaron Wood 6065e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo for (auto observer : daemon_state_->service_observers()) { 6077f92e2b7060cb35719acf96ef96a4e273e165bc5Aaron Wood observer->SendStatusUpdate(status_to_send); 6085e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo } 6095e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo last_notify_time_ = TimeTicks::Now(); 6105e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 6115e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6122c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymovoid UpdateAttempterAndroid::BuildUpdateActions(const string& url) { 6135e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo CHECK(!processor_->IsRunning()); 6145e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo processor_->set_delegate(this); 6155e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6165e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Actions: 6175e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo shared_ptr<InstallPlanAction> install_plan_action( 6185e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo new InstallPlanAction(install_plan_)); 6195e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6202c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo HttpFetcher* download_fetcher = nullptr; 6212c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo if (FileFetcher::SupportedUrl(url)) { 6222c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo DLOG(INFO) << "Using FileFetcher for file URL."; 6232c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo download_fetcher = new FileFetcher(); 6242c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo } else { 62514c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo#ifdef _UE_SIDELOAD 62614c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo LOG(FATAL) << "Unsupported sideload URI: " << url; 62714c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo#else 6282c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo LibcurlHttpFetcher* libcurl_fetcher = 6292c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo new LibcurlHttpFetcher(&proxy_resolver_, hardware_); 6302c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload); 6312c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo download_fetcher = libcurl_fetcher; 63214c0da88a93aa7b1aa71d5e7e923b537f0d419f3Alex Deymo#endif // _UE_SIDELOAD 6332c131bbf81d8c02ade163b939c96e44aa93765e9Alex Deymo } 6345ae865b431cc041feed82f1db28a38e99dbd631fSen Jiang shared_ptr<DownloadAction> download_action( 6355ae865b431cc041feed82f1db28a38e99dbd631fSen Jiang new DownloadAction(prefs_, 6365ae865b431cc041feed82f1db28a38e99dbd631fSen Jiang boot_control_, 6375ae865b431cc041feed82f1db28a38e99dbd631fSen Jiang hardware_, 63844906965d0809992052e47e11809ec730813d8b0Sen Jiang nullptr, // system_state, not used. 63944906965d0809992052e47e11809ec730813d8b0Sen Jiang download_fetcher, // passes ownership 6407ecda265a87236e83cf820364947a1618872b6beAmin Hassani true /* is_interactive */)); 641fef85fd9ece49941db274559a938fe8b2c5157bfSen Jiang shared_ptr<FilesystemVerifierAction> filesystem_verifier_action( 642e6e4bb929acd73e57b68a30d1e3a33d76607aec3Sen Jiang new FilesystemVerifierAction()); 6435e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6445e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo shared_ptr<PostinstallRunnerAction> postinstall_runner_action( 645fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo new PostinstallRunnerAction(boot_control_, hardware_)); 6465e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6475e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo download_action->set_delegate(this); 6485ae865b431cc041feed82f1db28a38e99dbd631fSen Jiang download_action->set_base_offset(base_offset_); 6495e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo download_action_ = download_action; 650b6eef73e20736b4b6a43611fa732d8bba72ff7ffAlex Deymo postinstall_runner_action->set_delegate(this); 6515e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6525e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo actions_.push_back(shared_ptr<AbstractAction>(install_plan_action)); 6535e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo actions_.push_back(shared_ptr<AbstractAction>(download_action)); 654fef85fd9ece49941db274559a938fe8b2c5157bfSen Jiang actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action)); 6555e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action)); 6565e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6575e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Bond them together. We have to use the leaf-types when calling 6585e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // BondActions(). 6595e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo BondActions(install_plan_action.get(), download_action.get()); 660fef85fd9ece49941db274559a938fe8b2c5157bfSen Jiang BondActions(download_action.get(), filesystem_verifier_action.get()); 661fef85fd9ece49941db274559a938fe8b2c5157bfSen Jiang BondActions(filesystem_verifier_action.get(), 6625e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo postinstall_runner_action.get()); 6635e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6645e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // Enqueue the actions. 6655e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo for (const shared_ptr<AbstractAction>& action : actions_) 6665e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo processor_->EnqueueAction(action.get()); 6675e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 6685e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6695e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::WriteUpdateCompletedMarker() { 6705e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo string boot_id; 6715e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id)); 6725e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id); 6735e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return true; 6745e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 6755e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6765e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymobool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() { 6775e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // In case of an update_engine restart without a reboot, we stored the boot_id 6785e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // when the update was completed by setting a pref, so we can check whether 6795e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo // the last update was on this boot or a previous one. 6805e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo string boot_id; 6815e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id)); 6825e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 6835e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo string update_completed_on_boot_id; 6845e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) && 6855e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo prefs_->GetString(kPrefsUpdateCompletedOnBootId, 6865e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo &update_completed_on_boot_id) && 6875e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo update_completed_on_boot_id == boot_id); 6885e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} 6895e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo 69090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu// Collect and report the android metrics when we terminate the update. 69190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xuvoid UpdateAttempterAndroid::CollectAndReportUpdateMetricsOnUpdateFinished( 69290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu ErrorCode error_code) { 69390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu int64_t attempt_number = 69490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_); 69590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu PayloadType payload_type = kPayloadTypeFull; 69690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu int64_t payload_size = 0; 69790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu for (const auto& p : install_plan_.payloads) { 69890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (p.type == InstallPayloadType::kDelta) 69990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu payload_type = kPayloadTypeDelta; 70090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu payload_size += p.size; 70190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 70290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 70390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics::AttemptResult attempt_result = 70490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::GetAttemptResult(error_code); 70590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu Time attempt_start_time = Time::FromInternalValue( 70690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::GetPersistedValue(kPrefsUpdateTimestampStart, prefs_)); 70752c678cddc5dd7bda8a29e74ce6ef4d67e8d1487Tianjie Xu TimeDelta duration = clock_->GetBootTime() - attempt_start_time; 70890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu TimeDelta duration_uptime = clock_->GetMonotonicTime() - attempt_start_time; 70990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 71090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_reporter_->ReportUpdateAttemptMetrics( 71190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu nullptr, // system_state 71290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu static_cast<int>(attempt_number), 71390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu payload_type, 71452c678cddc5dd7bda8a29e74ce6ef4d67e8d1487Tianjie Xu duration, 71590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu duration_uptime, 71690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu payload_size, 71790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu attempt_result, 71890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu error_code); 71990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 720d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu int64_t current_bytes_downloaded = 721d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_); 722d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics_reporter_->ReportUpdateAttemptDownloadMetrics( 723d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu current_bytes_downloaded, 724d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu 0, 725d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu DownloadSource::kNumDownloadSources, 726d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics::DownloadErrorCode::kUnset, 727d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics::ConnectionType::kUnset); 728d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu 72990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (error_code == ErrorCode::kSuccess) { 73090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu int64_t reboot_count = 73190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_); 73290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu string build_version; 73390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->GetString(kPrefsPreviousVersion, &build_version); 734d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu 735d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu // For android metrics, we only care about the total bytes downloaded 736d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu // for all sources; for now we assume the only download source is 737d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu // HttpsServer. 738d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu int64_t total_bytes_downloaded = 739d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_); 740d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu int64_t num_bytes_downloaded[kNumDownloadSources] = {}; 741d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu num_bytes_downloaded[DownloadSource::kDownloadSourceHttpsServer] = 742d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu total_bytes_downloaded; 743d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu 744d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu int download_overhead_percentage = 0; 745d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu if (current_bytes_downloaded > 0) { 746d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu download_overhead_percentage = 747d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu (total_bytes_downloaded - current_bytes_downloaded) * 100ull / 748d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu current_bytes_downloaded; 749d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu } 75090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_reporter_->ReportSuccessfulUpdateMetrics( 75190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu static_cast<int>(attempt_number), 75290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 0, // update abandoned count 75390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu payload_type, 75490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu payload_size, 755d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu num_bytes_downloaded, 756d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu download_overhead_percentage, 75752c678cddc5dd7bda8a29e74ce6ef4d67e8d1487Tianjie Xu duration, 75890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu static_cast<int>(reboot_count), 75990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 0); // url_switch_count 76090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 76190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu} 76290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 76390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xuvoid UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() { 76490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu string current_boot_id; 76590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu TEST_AND_RETURN(utils::GetBootId(¤t_boot_id)); 76690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // Example: [ro.build.version.incremental]: [4292972] 76790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu string current_version = 76890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu android::base::GetProperty("ro.build.version.incremental", ""); 76990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu TEST_AND_RETURN(!current_version.empty()); 77090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 77190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // If there's no record of previous version (e.g. due to a data wipe), we 77290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // save the info of current boot and skip the metrics report. 77390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (!prefs_->Exists(kPrefsPreviousVersion)) { 77490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->SetString(kPrefsBootId, current_boot_id); 77590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->SetString(kPrefsPreviousVersion, current_version); 77690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu ClearMetricsPrefs(); 77790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu return; 77890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 77990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu string previous_version; 78090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // update_engine restarted under the same build. 78190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // TODO(xunchang) identify and report rollback by checking UpdateMarker. 78290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (prefs_->GetString(kPrefsPreviousVersion, &previous_version) && 78390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu previous_version == current_version) { 78490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu string last_boot_id; 78590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu bool is_reboot = prefs_->Exists(kPrefsBootId) && 78690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu (prefs_->GetString(kPrefsBootId, &last_boot_id) && 78790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu last_boot_id != current_boot_id); 78890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // Increment the reboot number if |kPrefsNumReboots| exists. That pref is 78990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // set when we start a new update. 79090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (is_reboot && prefs_->Exists(kPrefsNumReboots)) { 79190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->SetString(kPrefsBootId, current_boot_id); 79290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu int64_t reboot_count = 79390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_); 79490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::SetNumReboots(reboot_count + 1, prefs_); 79590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 79690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu return; 79790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 79890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 79990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // Now that the build version changes, report the update metrics. 80090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // TODO(xunchang) check the build version is larger than the previous one. 80190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->SetString(kPrefsBootId, current_boot_id); 80290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->SetString(kPrefsPreviousVersion, current_version); 80390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 80490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu bool previous_attempt_exists = prefs_->Exists(kPrefsPayloadAttemptNumber); 80590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu // |kPrefsPayloadAttemptNumber| should be cleared upon successful update. 80690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (previous_attempt_exists) { 80790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_reporter_->ReportAbnormallyTerminatedUpdateAttemptMetrics(); 80890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 80990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 81090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::LoadAndReportTimeToReboot( 81190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_reporter_.get(), prefs_, clock_.get()); 81290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu ClearMetricsPrefs(); 81390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu} 81490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 81590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu// Save the update start time. Reset the reboot count and attempt number if the 81690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu// update isn't a resume; otherwise increment the attempt number. 81790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xuvoid UpdateAttempterAndroid::UpdatePrefsOnUpdateStart(bool is_resume) { 81890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu if (!is_resume) { 81990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::SetNumReboots(0, prefs_); 82090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::SetPayloadAttemptNumber(1, prefs_); 82190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } else { 82290aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu int64_t attempt_number = 82390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_); 82490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::SetPayloadAttemptNumber(attempt_number + 1, prefs_); 82590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu } 82690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu Time update_start_time = clock_->GetMonotonicTime(); 82790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu metrics_utils::SetUpdateTimestampStart(update_start_time, prefs_); 82890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu} 82990aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 83090aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xuvoid UpdateAttempterAndroid::ClearMetricsPrefs() { 83190aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu CHECK(prefs_); 832d4777a148bc822ca11b8355a9df733a5798852c1Tianjie Xu prefs_->Delete(kPrefsCurrentBytesDownloaded); 83390aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->Delete(kPrefsNumReboots); 83490aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->Delete(kPrefsPayloadAttemptNumber); 83590aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->Delete(kPrefsSystemUpdatedMarker); 83690aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu prefs_->Delete(kPrefsUpdateTimestampStart); 83790aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu} 83890aaa109e38f147ec4bfc772439d9949f1b237c0Tianjie Xu 8395e3ea278d9e771be3b51bd72985ad582678baddcAlex Deymo} // namespace chromeos_update_engine 840