xref: /aosp_15_r20/system/update_engine/aosp/update_attempter_android.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2016 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/update_attempter_android.h"
18*5a923131SAndroid Build Coastguard Worker 
19*5a923131SAndroid Build Coastguard Worker #include <algorithm>
20*5a923131SAndroid Build Coastguard Worker #include <map>
21*5a923131SAndroid Build Coastguard Worker #include <memory>
22*5a923131SAndroid Build Coastguard Worker #include <ostream>
23*5a923131SAndroid Build Coastguard Worker #include <utility>
24*5a923131SAndroid Build Coastguard Worker #include <vector>
25*5a923131SAndroid Build Coastguard Worker 
26*5a923131SAndroid Build Coastguard Worker #include <android-base/parsebool.h>
27*5a923131SAndroid Build Coastguard Worker #include <android-base/parseint.h>
28*5a923131SAndroid Build Coastguard Worker #include <android-base/properties.h>
29*5a923131SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
30*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
31*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
32*5a923131SAndroid Build Coastguard Worker #include <brillo/data_encoding.h>
33*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop.h>
34*5a923131SAndroid Build Coastguard Worker #include <brillo/strings/string_utils.h>
35*5a923131SAndroid Build Coastguard Worker #include <log/log_safetynet.h>
36*5a923131SAndroid Build Coastguard Worker 
37*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/cleanup_previous_update_action.h"
38*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/clock.h"
39*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/constants.h"
40*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/daemon_state_interface.h"
41*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/download_action.h"
42*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/error_code.h"
43*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/error_code_utils.h"
44*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/file_fetcher.h"
45*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/metrics_reporter_interface.h"
46*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/network_selector.h"
47*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
48*5a923131SAndroid Build Coastguard Worker #include "update_engine/metrics_utils.h"
49*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/delta_performer.h"
50*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/file_descriptor.h"
51*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/file_descriptor_utils.h"
52*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/filesystem_verifier_action.h"
53*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/partition_writer.h"
54*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/payload_constants.h"
55*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/payload_metadata.h"
56*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/payload_verifier.h"
57*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_consumer/postinstall_runner_action.h"
58*5a923131SAndroid Build Coastguard Worker #include "update_engine/update_boot_flags_action.h"
59*5a923131SAndroid Build Coastguard Worker #include "update_engine/update_status.h"
60*5a923131SAndroid Build Coastguard Worker #include "update_engine/update_status_utils.h"
61*5a923131SAndroid Build Coastguard Worker 
62*5a923131SAndroid Build Coastguard Worker #ifndef _UE_SIDELOAD
63*5a923131SAndroid Build Coastguard Worker // Do not include support for external HTTP(s) urls when building
64*5a923131SAndroid Build Coastguard Worker // update_engine_sideload.
65*5a923131SAndroid Build Coastguard Worker #include "update_engine/libcurl_http_fetcher.h"
66*5a923131SAndroid Build Coastguard Worker #endif
67*5a923131SAndroid Build Coastguard Worker 
68*5a923131SAndroid Build Coastguard Worker using android::base::unique_fd;
69*5a923131SAndroid Build Coastguard Worker using base::Bind;
70*5a923131SAndroid Build Coastguard Worker using base::Time;
71*5a923131SAndroid Build Coastguard Worker using base::TimeDelta;
72*5a923131SAndroid Build Coastguard Worker using base::TimeTicks;
73*5a923131SAndroid Build Coastguard Worker using std::string;
74*5a923131SAndroid Build Coastguard Worker using std::vector;
75*5a923131SAndroid Build Coastguard Worker using update_engine::UpdateEngineStatus;
76*5a923131SAndroid Build Coastguard Worker 
77*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
78*5a923131SAndroid Build Coastguard Worker 
79*5a923131SAndroid Build Coastguard Worker namespace {
80*5a923131SAndroid Build Coastguard Worker 
81*5a923131SAndroid Build Coastguard Worker // Minimum threshold to broadcast an status update in progress and time.
82*5a923131SAndroid Build Coastguard Worker const double kBroadcastThresholdProgress = 0.01;  // 1%
83*5a923131SAndroid Build Coastguard Worker const int kBroadcastThresholdSeconds = 10;
84*5a923131SAndroid Build Coastguard Worker 
85*5a923131SAndroid Build Coastguard Worker // Log and set the error on the passed ErrorPtr.
LogAndSetGenericError(Error * error,int line_number,const char * file_name,const string & reason)86*5a923131SAndroid Build Coastguard Worker bool LogAndSetGenericError(Error* error,
87*5a923131SAndroid Build Coastguard Worker                            int line_number,
88*5a923131SAndroid Build Coastguard Worker                            const char* file_name,
89*5a923131SAndroid Build Coastguard Worker                            const string& reason) {
90*5a923131SAndroid Build Coastguard Worker   LOG(ERROR) << "Replying with failure: " << file_name << " " << line_number
91*5a923131SAndroid Build Coastguard Worker              << ": " << reason;
92*5a923131SAndroid Build Coastguard Worker   error->line_number = line_number;
93*5a923131SAndroid Build Coastguard Worker   error->file_name = file_name;
94*5a923131SAndroid Build Coastguard Worker   error->message = reason;
95*5a923131SAndroid Build Coastguard Worker   error->error_code = ErrorCode::kError;
96*5a923131SAndroid Build Coastguard Worker   return false;
97*5a923131SAndroid Build Coastguard Worker }
98*5a923131SAndroid Build Coastguard Worker 
99*5a923131SAndroid Build Coastguard Worker // Log and set the error on the passed ErrorPtr.
LogAndSetError(Error * error,int line_number,const char * file_name,const string & reason,ErrorCode error_code)100*5a923131SAndroid Build Coastguard Worker bool LogAndSetError(Error* error,
101*5a923131SAndroid Build Coastguard Worker                     int line_number,
102*5a923131SAndroid Build Coastguard Worker                     const char* file_name,
103*5a923131SAndroid Build Coastguard Worker                     const string& reason,
104*5a923131SAndroid Build Coastguard Worker                     ErrorCode error_code) {
105*5a923131SAndroid Build Coastguard Worker   LOG(ERROR) << "Replying with failure: " << file_name << " " << line_number
106*5a923131SAndroid Build Coastguard Worker              << ": " << reason;
107*5a923131SAndroid Build Coastguard Worker   error->line_number = line_number;
108*5a923131SAndroid Build Coastguard Worker   error->file_name = file_name;
109*5a923131SAndroid Build Coastguard Worker   error->message = reason;
110*5a923131SAndroid Build Coastguard Worker   error->error_code = error_code;
111*5a923131SAndroid Build Coastguard Worker   return false;
112*5a923131SAndroid Build Coastguard Worker }
113*5a923131SAndroid Build Coastguard Worker 
GetHeaderAsBool(const string & header,bool default_value)114*5a923131SAndroid Build Coastguard Worker bool GetHeaderAsBool(const string& header, bool default_value) {
115*5a923131SAndroid Build Coastguard Worker   int value = 0;
116*5a923131SAndroid Build Coastguard Worker   if (android::base::ParseInt(header, &value) && (value == 0 || value == 1))
117*5a923131SAndroid Build Coastguard Worker     return value == 1;
118*5a923131SAndroid Build Coastguard Worker   return default_value;
119*5a923131SAndroid Build Coastguard Worker }
120*5a923131SAndroid Build Coastguard Worker 
ParseKeyValuePairHeaders(const vector<string> & key_value_pair_headers,std::map<string,string> * headers,Error * error)121*5a923131SAndroid Build Coastguard Worker bool ParseKeyValuePairHeaders(const vector<string>& key_value_pair_headers,
122*5a923131SAndroid Build Coastguard Worker                               std::map<string, string>* headers,
123*5a923131SAndroid Build Coastguard Worker                               Error* error) {
124*5a923131SAndroid Build Coastguard Worker   for (const string& key_value_pair : key_value_pair_headers) {
125*5a923131SAndroid Build Coastguard Worker     string key;
126*5a923131SAndroid Build Coastguard Worker     string value;
127*5a923131SAndroid Build Coastguard Worker     if (!brillo::string_utils::SplitAtFirst(
128*5a923131SAndroid Build Coastguard Worker             key_value_pair, "=", &key, &value, false)) {
129*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(error,
130*5a923131SAndroid Build Coastguard Worker                                    __LINE__,
131*5a923131SAndroid Build Coastguard Worker                                    __FILE__,
132*5a923131SAndroid Build Coastguard Worker                                    "Passed invalid header: " + key_value_pair);
133*5a923131SAndroid Build Coastguard Worker     }
134*5a923131SAndroid Build Coastguard Worker     if (!headers->emplace(key, value).second)
135*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(
136*5a923131SAndroid Build Coastguard Worker           error, __LINE__, __FILE__, "Passed repeated key: " + key);
137*5a923131SAndroid Build Coastguard Worker   }
138*5a923131SAndroid Build Coastguard Worker   return true;
139*5a923131SAndroid Build Coastguard Worker }
140*5a923131SAndroid Build Coastguard Worker 
141*5a923131SAndroid Build Coastguard Worker // Unique identifier for the payload. An empty string means that the payload
142*5a923131SAndroid Build Coastguard Worker // can't be resumed.
GetPayloadId(const std::map<string,string> & headers)143*5a923131SAndroid Build Coastguard Worker string GetPayloadId(const std::map<string, string>& headers) {
144*5a923131SAndroid Build Coastguard Worker   return (headers.count(kPayloadPropertyFileHash)
145*5a923131SAndroid Build Coastguard Worker               ? headers.at(kPayloadPropertyFileHash)
146*5a923131SAndroid Build Coastguard Worker               : "") +
147*5a923131SAndroid Build Coastguard Worker          (headers.count(kPayloadPropertyMetadataHash)
148*5a923131SAndroid Build Coastguard Worker               ? headers.at(kPayloadPropertyMetadataHash)
149*5a923131SAndroid Build Coastguard Worker               : "");
150*5a923131SAndroid Build Coastguard Worker }
151*5a923131SAndroid Build Coastguard Worker 
GetCurrentBuildVersion()152*5a923131SAndroid Build Coastguard Worker std::string GetCurrentBuildVersion() {
153*5a923131SAndroid Build Coastguard Worker   // Example: [ro.build.fingerprint]:
154*5a923131SAndroid Build Coastguard Worker   // [generic/aosp_cf_x86_64_phone/vsoc_x86_64:VanillaIceCream/AOSP.MAIN/user08011303:userdebug/test-keys]
155*5a923131SAndroid Build Coastguard Worker   return android::base::GetProperty("ro.build.fingerprint", "");
156*5a923131SAndroid Build Coastguard Worker }
157*5a923131SAndroid Build Coastguard Worker 
158*5a923131SAndroid Build Coastguard Worker }  // namespace
159*5a923131SAndroid Build Coastguard Worker 
UpdateAttempterAndroid(DaemonStateInterface * daemon_state,PrefsInterface * prefs,BootControlInterface * boot_control,HardwareInterface * hardware,std::unique_ptr<ApexHandlerInterface> apex_handler)160*5a923131SAndroid Build Coastguard Worker UpdateAttempterAndroid::UpdateAttempterAndroid(
161*5a923131SAndroid Build Coastguard Worker     DaemonStateInterface* daemon_state,
162*5a923131SAndroid Build Coastguard Worker     PrefsInterface* prefs,
163*5a923131SAndroid Build Coastguard Worker     BootControlInterface* boot_control,
164*5a923131SAndroid Build Coastguard Worker     HardwareInterface* hardware,
165*5a923131SAndroid Build Coastguard Worker     std::unique_ptr<ApexHandlerInterface> apex_handler)
166*5a923131SAndroid Build Coastguard Worker     : daemon_state_(daemon_state),
167*5a923131SAndroid Build Coastguard Worker       prefs_(prefs),
168*5a923131SAndroid Build Coastguard Worker       boot_control_(boot_control),
169*5a923131SAndroid Build Coastguard Worker       hardware_(hardware),
170*5a923131SAndroid Build Coastguard Worker       apex_handler_android_(std::move(apex_handler)),
171*5a923131SAndroid Build Coastguard Worker       processor_(new ActionProcessor()),
172*5a923131SAndroid Build Coastguard Worker       clock_(new Clock()),
173*5a923131SAndroid Build Coastguard Worker       metric_bytes_downloaded_(kPrefsCurrentBytesDownloaded, prefs_),
174*5a923131SAndroid Build Coastguard Worker       metric_total_bytes_downloaded_(kPrefsTotalBytesDownloaded, prefs_) {
175*5a923131SAndroid Build Coastguard Worker   metrics_reporter_ = metrics::CreateMetricsReporter(
176*5a923131SAndroid Build Coastguard Worker       boot_control_->GetDynamicPartitionControl(), &install_plan_);
177*5a923131SAndroid Build Coastguard Worker   network_selector_ = network::CreateNetworkSelector();
178*5a923131SAndroid Build Coastguard Worker }
179*5a923131SAndroid Build Coastguard Worker 
~UpdateAttempterAndroid()180*5a923131SAndroid Build Coastguard Worker UpdateAttempterAndroid::~UpdateAttempterAndroid() {
181*5a923131SAndroid Build Coastguard Worker   // Release ourselves as the ActionProcessor's delegate to prevent
182*5a923131SAndroid Build Coastguard Worker   // re-scheduling the updates due to the processing stopped.
183*5a923131SAndroid Build Coastguard Worker   processor_->set_delegate(nullptr);
184*5a923131SAndroid Build Coastguard Worker }
185*5a923131SAndroid Build Coastguard Worker 
DidSystemReboot(PrefsInterface * prefs)186*5a923131SAndroid Build Coastguard Worker [[nodiscard]] static bool DidSystemReboot(PrefsInterface* prefs) {
187*5a923131SAndroid Build Coastguard Worker   string boot_id;
188*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
189*5a923131SAndroid Build Coastguard Worker   string old_boot_id;
190*5a923131SAndroid Build Coastguard Worker   // If no previous boot id found, treat as a reboot and write boot ID.
191*5a923131SAndroid Build Coastguard Worker   if (!prefs->GetString(kPrefsBootId, &old_boot_id)) {
192*5a923131SAndroid Build Coastguard Worker     return true;
193*5a923131SAndroid Build Coastguard Worker   }
194*5a923131SAndroid Build Coastguard Worker   return old_boot_id != boot_id;
195*5a923131SAndroid Build Coastguard Worker }
196*5a923131SAndroid Build Coastguard Worker 
operator <<(std::ostream & out,OTAResult result)197*5a923131SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, OTAResult result) {
198*5a923131SAndroid Build Coastguard Worker   switch (result) {
199*5a923131SAndroid Build Coastguard Worker     case OTAResult::NOT_ATTEMPTED:
200*5a923131SAndroid Build Coastguard Worker       out << "OTAResult::NOT_ATTEMPTED";
201*5a923131SAndroid Build Coastguard Worker       break;
202*5a923131SAndroid Build Coastguard Worker     case OTAResult::ROLLED_BACK:
203*5a923131SAndroid Build Coastguard Worker       out << "OTAResult::ROLLED_BACK";
204*5a923131SAndroid Build Coastguard Worker       break;
205*5a923131SAndroid Build Coastguard Worker     case OTAResult::UPDATED_NEED_REBOOT:
206*5a923131SAndroid Build Coastguard Worker       out << "OTAResult::UPDATED_NEED_REBOOT";
207*5a923131SAndroid Build Coastguard Worker       break;
208*5a923131SAndroid Build Coastguard Worker     case OTAResult::OTA_SUCCESSFUL:
209*5a923131SAndroid Build Coastguard Worker       out << "OTAResult::OTA_SUCCESSFUL";
210*5a923131SAndroid Build Coastguard Worker       break;
211*5a923131SAndroid Build Coastguard Worker   }
212*5a923131SAndroid Build Coastguard Worker   return out;
213*5a923131SAndroid Build Coastguard Worker }
214*5a923131SAndroid Build Coastguard Worker 
Init()215*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::Init() {
216*5a923131SAndroid Build Coastguard Worker   // In case of update_engine restart without a reboot we need to restore the
217*5a923131SAndroid Build Coastguard Worker   // reboot needed state.
218*5a923131SAndroid Build Coastguard Worker   if (UpdateCompletedOnThisBoot()) {
219*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Updated installed but update_engine is restarted without "
220*5a923131SAndroid Build Coastguard Worker                  "device reboot. Resuming old state.";
221*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
222*5a923131SAndroid Build Coastguard Worker   } else {
223*5a923131SAndroid Build Coastguard Worker     const auto result = GetOTAUpdateResult();
224*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << result;
225*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::IDLE);
226*5a923131SAndroid Build Coastguard Worker     if (DidSystemReboot(prefs_)) {
227*5a923131SAndroid Build Coastguard Worker       UpdateStateAfterReboot(result);
228*5a923131SAndroid Build Coastguard Worker     }
229*5a923131SAndroid Build Coastguard Worker 
230*5a923131SAndroid Build Coastguard Worker #ifdef _UE_SIDELOAD
231*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Skip ScheduleCleanupPreviousUpdate in sideload because "
232*5a923131SAndroid Build Coastguard Worker               << "ApplyPayload will call it later.";
233*5a923131SAndroid Build Coastguard Worker #else
234*5a923131SAndroid Build Coastguard Worker     ScheduleCleanupPreviousUpdate();
235*5a923131SAndroid Build Coastguard Worker #endif
236*5a923131SAndroid Build Coastguard Worker   }
237*5a923131SAndroid Build Coastguard Worker }
238*5a923131SAndroid Build Coastguard Worker 
ApplyPayload(const string & payload_url,int64_t payload_offset,int64_t payload_size,const vector<string> & key_value_pair_headers,Error * error)239*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::ApplyPayload(
240*5a923131SAndroid Build Coastguard Worker     const string& payload_url,
241*5a923131SAndroid Build Coastguard Worker     int64_t payload_offset,
242*5a923131SAndroid Build Coastguard Worker     int64_t payload_size,
243*5a923131SAndroid Build Coastguard Worker     const vector<string>& key_value_pair_headers,
244*5a923131SAndroid Build Coastguard Worker     Error* error) {
245*5a923131SAndroid Build Coastguard Worker   if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
246*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
247*5a923131SAndroid Build Coastguard Worker                           __LINE__,
248*5a923131SAndroid Build Coastguard Worker                           __FILE__,
249*5a923131SAndroid Build Coastguard Worker                           "An update already applied, waiting for reboot",
250*5a923131SAndroid Build Coastguard Worker                           ErrorCode::kUpdateAlreadyInstalled);
251*5a923131SAndroid Build Coastguard Worker   }
252*5a923131SAndroid Build Coastguard Worker   if (processor_->IsRunning()) {
253*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
254*5a923131SAndroid Build Coastguard Worker                           __LINE__,
255*5a923131SAndroid Build Coastguard Worker                           __FILE__,
256*5a923131SAndroid Build Coastguard Worker                           "Already processing an update, cancel it first.",
257*5a923131SAndroid Build Coastguard Worker                           ErrorCode::kUpdateProcessing);
258*5a923131SAndroid Build Coastguard Worker   }
259*5a923131SAndroid Build Coastguard Worker   DCHECK_EQ(status_, UpdateStatus::IDLE);
260*5a923131SAndroid Build Coastguard Worker 
261*5a923131SAndroid Build Coastguard Worker   std::map<string, string> headers;
262*5a923131SAndroid Build Coastguard Worker   if (!ParseKeyValuePairHeaders(key_value_pair_headers, &headers, error)) {
263*5a923131SAndroid Build Coastguard Worker     return false;
264*5a923131SAndroid Build Coastguard Worker   }
265*5a923131SAndroid Build Coastguard Worker 
266*5a923131SAndroid Build Coastguard Worker   string payload_id = GetPayloadId(headers);
267*5a923131SAndroid Build Coastguard Worker 
268*5a923131SAndroid Build Coastguard Worker   // Setup the InstallPlan based on the request.
269*5a923131SAndroid Build Coastguard Worker   install_plan_ = InstallPlan();
270*5a923131SAndroid Build Coastguard Worker 
271*5a923131SAndroid Build Coastguard Worker   install_plan_.download_url = payload_url;
272*5a923131SAndroid Build Coastguard Worker   install_plan_.version = "";
273*5a923131SAndroid Build Coastguard Worker   base_offset_ = payload_offset;
274*5a923131SAndroid Build Coastguard Worker   InstallPlan::Payload payload;
275*5a923131SAndroid Build Coastguard Worker   payload.size = payload_size;
276*5a923131SAndroid Build Coastguard Worker   if (!payload.size) {
277*5a923131SAndroid Build Coastguard Worker     if (!android::base::ParseUint<uint64_t>(headers[kPayloadPropertyFileSize],
278*5a923131SAndroid Build Coastguard Worker                                             &payload.size)) {
279*5a923131SAndroid Build Coastguard Worker       payload.size = 0;
280*5a923131SAndroid Build Coastguard Worker     }
281*5a923131SAndroid Build Coastguard Worker   }
282*5a923131SAndroid Build Coastguard Worker   if (!brillo::data_encoding::Base64Decode(headers[kPayloadPropertyFileHash],
283*5a923131SAndroid Build Coastguard Worker                                            &payload.hash)) {
284*5a923131SAndroid Build Coastguard Worker     LOG(WARNING) << "Unable to decode base64 file hash: "
285*5a923131SAndroid Build Coastguard Worker                  << headers[kPayloadPropertyFileHash];
286*5a923131SAndroid Build Coastguard Worker   }
287*5a923131SAndroid Build Coastguard Worker   if (!android::base::ParseUint<uint64_t>(headers[kPayloadPropertyMetadataSize],
288*5a923131SAndroid Build Coastguard Worker                                           &payload.metadata_size)) {
289*5a923131SAndroid Build Coastguard Worker     payload.metadata_size = 0;
290*5a923131SAndroid Build Coastguard Worker   }
291*5a923131SAndroid Build Coastguard Worker   // The |payload.type| is not used anymore since minor_version 3.
292*5a923131SAndroid Build Coastguard Worker   payload.type = InstallPayloadType::kUnknown;
293*5a923131SAndroid Build Coastguard Worker   install_plan_.payloads.push_back(payload);
294*5a923131SAndroid Build Coastguard Worker 
295*5a923131SAndroid Build Coastguard Worker   // The |public_key_rsa| key would override the public key stored on disk.
296*5a923131SAndroid Build Coastguard Worker   install_plan_.public_key_rsa = "";
297*5a923131SAndroid Build Coastguard Worker 
298*5a923131SAndroid Build Coastguard Worker   install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
299*5a923131SAndroid Build Coastguard Worker   install_plan_.is_resume = !payload_id.empty() &&
300*5a923131SAndroid Build Coastguard Worker                             DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
301*5a923131SAndroid Build Coastguard Worker   if (!install_plan_.is_resume) {
302*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Starting a new update " << payload_url
303*5a923131SAndroid Build Coastguard Worker               << " size: " << payload_size << " offset: " << payload_offset;
304*5a923131SAndroid Build Coastguard Worker     boot_control_->GetDynamicPartitionControl()->Cleanup();
305*5a923131SAndroid Build Coastguard Worker     boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_);
306*5a923131SAndroid Build Coastguard Worker 
307*5a923131SAndroid Build Coastguard Worker     if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
308*5a923131SAndroid Build Coastguard Worker       LOG(WARNING) << "Unable to save the update check response hash.";
309*5a923131SAndroid Build Coastguard Worker     }
310*5a923131SAndroid Build Coastguard Worker   }
311*5a923131SAndroid Build Coastguard Worker   install_plan_.source_slot = GetCurrentSlot();
312*5a923131SAndroid Build Coastguard Worker   install_plan_.target_slot = GetTargetSlot();
313*5a923131SAndroid Build Coastguard Worker 
314*5a923131SAndroid Build Coastguard Worker   install_plan_.powerwash_required =
315*5a923131SAndroid Build Coastguard Worker       GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false);
316*5a923131SAndroid Build Coastguard Worker 
317*5a923131SAndroid Build Coastguard Worker   install_plan_.spl_downgrade =
318*5a923131SAndroid Build Coastguard Worker       GetHeaderAsBool(headers[kPayloadPropertySplDowngrade], false);
319*5a923131SAndroid Build Coastguard Worker 
320*5a923131SAndroid Build Coastguard Worker   if (!IsProductionBuild()) {
321*5a923131SAndroid Build Coastguard Worker     install_plan_.disable_vabc =
322*5a923131SAndroid Build Coastguard Worker         GetHeaderAsBool(headers[kPayloadDisableVABC], false);
323*5a923131SAndroid Build Coastguard Worker   }
324*5a923131SAndroid Build Coastguard Worker 
325*5a923131SAndroid Build Coastguard Worker   install_plan_.switch_slot_on_reboot =
326*5a923131SAndroid Build Coastguard Worker       GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true);
327*5a923131SAndroid Build Coastguard Worker 
328*5a923131SAndroid Build Coastguard Worker   install_plan_.run_post_install =
329*5a923131SAndroid Build Coastguard Worker       GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
330*5a923131SAndroid Build Coastguard Worker 
331*5a923131SAndroid Build Coastguard Worker   // Skip writing verity if we're resuming and verity has already been written.
332*5a923131SAndroid Build Coastguard Worker   install_plan_.write_verity = true;
333*5a923131SAndroid Build Coastguard Worker   if (install_plan_.is_resume && prefs_->Exists(kPrefsVerityWritten)) {
334*5a923131SAndroid Build Coastguard Worker     bool verity_written = false;
335*5a923131SAndroid Build Coastguard Worker     if (prefs_->GetBoolean(kPrefsVerityWritten, &verity_written) &&
336*5a923131SAndroid Build Coastguard Worker         verity_written) {
337*5a923131SAndroid Build Coastguard Worker       install_plan_.write_verity = false;
338*5a923131SAndroid Build Coastguard Worker     }
339*5a923131SAndroid Build Coastguard Worker   }
340*5a923131SAndroid Build Coastguard Worker 
341*5a923131SAndroid Build Coastguard Worker   NetworkId network_id = kDefaultNetworkId;
342*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadPropertyNetworkId].empty()) {
343*5a923131SAndroid Build Coastguard Worker     if (!android::base::ParseUint<uint64_t>(headers[kPayloadPropertyNetworkId],
344*5a923131SAndroid Build Coastguard Worker                                             &network_id)) {
345*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(
346*5a923131SAndroid Build Coastguard Worker           error,
347*5a923131SAndroid Build Coastguard Worker           __LINE__,
348*5a923131SAndroid Build Coastguard Worker           __FILE__,
349*5a923131SAndroid Build Coastguard Worker           "Invalid network_id: " + headers[kPayloadPropertyNetworkId]);
350*5a923131SAndroid Build Coastguard Worker     }
351*5a923131SAndroid Build Coastguard Worker     if (!network_selector_->SetProcessNetwork(network_id)) {
352*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(
353*5a923131SAndroid Build Coastguard Worker           error,
354*5a923131SAndroid Build Coastguard Worker           __LINE__,
355*5a923131SAndroid Build Coastguard Worker           __FILE__,
356*5a923131SAndroid Build Coastguard Worker           "Unable to set network_id: " + headers[kPayloadPropertyNetworkId]);
357*5a923131SAndroid Build Coastguard Worker     }
358*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Using network ID: " << network_id;
359*5a923131SAndroid Build Coastguard Worker   }
360*5a923131SAndroid Build Coastguard Worker 
361*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Using this install plan:";
362*5a923131SAndroid Build Coastguard Worker   install_plan_.Dump();
363*5a923131SAndroid Build Coastguard Worker 
364*5a923131SAndroid Build Coastguard Worker   HttpFetcher* fetcher = nullptr;
365*5a923131SAndroid Build Coastguard Worker   if (FileFetcher::SupportedUrl(payload_url)) {
366*5a923131SAndroid Build Coastguard Worker     DLOG(INFO) << "Using FileFetcher for file URL.";
367*5a923131SAndroid Build Coastguard Worker     fetcher = new FileFetcher();
368*5a923131SAndroid Build Coastguard Worker   } else {
369*5a923131SAndroid Build Coastguard Worker #ifdef _UE_SIDELOAD
370*5a923131SAndroid Build Coastguard Worker     LOG(FATAL) << "Unsupported sideload URI: " << payload_url;
371*5a923131SAndroid Build Coastguard Worker     return false;  // NOLINT, unreached but analyzer might not know.
372*5a923131SAndroid Build Coastguard Worker                    // Suppress warnings about null 'fetcher' after this.
373*5a923131SAndroid Build Coastguard Worker #else
374*5a923131SAndroid Build Coastguard Worker     LibcurlHttpFetcher* libcurl_fetcher = new LibcurlHttpFetcher(hardware_);
375*5a923131SAndroid Build Coastguard Worker     if (!headers[kPayloadDownloadRetry].empty()) {
376*5a923131SAndroid Build Coastguard Worker       libcurl_fetcher->set_max_retry_count(
377*5a923131SAndroid Build Coastguard Worker           atoi(headers[kPayloadDownloadRetry].c_str()));
378*5a923131SAndroid Build Coastguard Worker     }
379*5a923131SAndroid Build Coastguard Worker     libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
380*5a923131SAndroid Build Coastguard Worker     fetcher = libcurl_fetcher;
381*5a923131SAndroid Build Coastguard Worker #endif  // _UE_SIDELOAD
382*5a923131SAndroid Build Coastguard Worker   }
383*5a923131SAndroid Build Coastguard Worker   // Setup extra headers.
384*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadPropertyAuthorization].empty()) {
385*5a923131SAndroid Build Coastguard Worker     fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]);
386*5a923131SAndroid Build Coastguard Worker   }
387*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadPropertyUserAgent].empty()) {
388*5a923131SAndroid Build Coastguard Worker     fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
389*5a923131SAndroid Build Coastguard Worker   }
390*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadPropertyHTTPExtras].empty()) {
391*5a923131SAndroid Build Coastguard Worker     auto entries =
392*5a923131SAndroid Build Coastguard Worker         android::base::Split(headers[kPayloadPropertyHTTPExtras], " ");
393*5a923131SAndroid Build Coastguard Worker     for (auto& entry : entries) {
394*5a923131SAndroid Build Coastguard Worker       auto parts = android::base::Split(entry, ";");
395*5a923131SAndroid Build Coastguard Worker       if (parts.size() != 2) {
396*5a923131SAndroid Build Coastguard Worker         LOG(ERROR)
397*5a923131SAndroid Build Coastguard Worker             << "HTTP headers are not in expected format. "
398*5a923131SAndroid Build Coastguard Worker                "headers[kPayloadPropertyHTTPExtras] = key1;val1 key2;val2";
399*5a923131SAndroid Build Coastguard Worker         continue;
400*5a923131SAndroid Build Coastguard Worker       }
401*5a923131SAndroid Build Coastguard Worker       fetcher->SetHeader(parts[0], parts[1]);
402*5a923131SAndroid Build Coastguard Worker     }
403*5a923131SAndroid Build Coastguard Worker   }
404*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadPropertyNetworkProxy].empty()) {
405*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Using proxy url from payload headers: "
406*5a923131SAndroid Build Coastguard Worker               << headers[kPayloadPropertyNetworkProxy];
407*5a923131SAndroid Build Coastguard Worker     fetcher->SetProxies({headers[kPayloadPropertyNetworkProxy]});
408*5a923131SAndroid Build Coastguard Worker   }
409*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadVABCNone].empty()) {
410*5a923131SAndroid Build Coastguard Worker     install_plan_.vabc_none = true;
411*5a923131SAndroid Build Coastguard Worker   }
412*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadEnableThreading].empty()) {
413*5a923131SAndroid Build Coastguard Worker     const auto res = android::base::ParseBool(headers[kPayloadEnableThreading]);
414*5a923131SAndroid Build Coastguard Worker     if (res != android::base::ParseBoolResult::kError) {
415*5a923131SAndroid Build Coastguard Worker       install_plan_.enable_threading =
416*5a923131SAndroid Build Coastguard Worker           res == android::base::ParseBoolResult::kTrue;
417*5a923131SAndroid Build Coastguard Worker     }
418*5a923131SAndroid Build Coastguard Worker   }
419*5a923131SAndroid Build Coastguard Worker   if (!headers[kPayloadBatchedWrites].empty()) {
420*5a923131SAndroid Build Coastguard Worker     install_plan_.batched_writes = true;
421*5a923131SAndroid Build Coastguard Worker   }
422*5a923131SAndroid Build Coastguard Worker 
423*5a923131SAndroid Build Coastguard Worker   BuildUpdateActions(fetcher);
424*5a923131SAndroid Build Coastguard Worker 
425*5a923131SAndroid Build Coastguard Worker   SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
426*5a923131SAndroid Build Coastguard Worker 
427*5a923131SAndroid Build Coastguard Worker   UpdatePrefsOnUpdateStart(install_plan_.is_resume);
428*5a923131SAndroid Build Coastguard Worker   // TODO(xunchang) report the metrics for unresumable updates
429*5a923131SAndroid Build Coastguard Worker 
430*5a923131SAndroid Build Coastguard Worker   ScheduleProcessingStart();
431*5a923131SAndroid Build Coastguard Worker   return true;
432*5a923131SAndroid Build Coastguard Worker }
433*5a923131SAndroid Build Coastguard Worker 
ApplyPayload(int fd,int64_t payload_offset,int64_t payload_size,const vector<string> & key_value_pair_headers,Error * error)434*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::ApplyPayload(
435*5a923131SAndroid Build Coastguard Worker     int fd,
436*5a923131SAndroid Build Coastguard Worker     int64_t payload_offset,
437*5a923131SAndroid Build Coastguard Worker     int64_t payload_size,
438*5a923131SAndroid Build Coastguard Worker     const vector<string>& key_value_pair_headers,
439*5a923131SAndroid Build Coastguard Worker     Error* error) {
440*5a923131SAndroid Build Coastguard Worker   // update_engine state must be checked before modifying payload_fd_ otherwise
441*5a923131SAndroid Build Coastguard Worker   // already running update will be terminated (existing file descriptor will be
442*5a923131SAndroid Build Coastguard Worker   // closed)
443*5a923131SAndroid Build Coastguard Worker   if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
444*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
445*5a923131SAndroid Build Coastguard Worker         error,
446*5a923131SAndroid Build Coastguard Worker         __LINE__,
447*5a923131SAndroid Build Coastguard Worker         __FILE__,
448*5a923131SAndroid Build Coastguard Worker         "An update already applied, waiting for reboot");
449*5a923131SAndroid Build Coastguard Worker   }
450*5a923131SAndroid Build Coastguard Worker   if (processor_->IsRunning()) {
451*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
452*5a923131SAndroid Build Coastguard Worker         error,
453*5a923131SAndroid Build Coastguard Worker         __LINE__,
454*5a923131SAndroid Build Coastguard Worker         __FILE__,
455*5a923131SAndroid Build Coastguard Worker         "Already processing an update, cancel it first.");
456*5a923131SAndroid Build Coastguard Worker   }
457*5a923131SAndroid Build Coastguard Worker   DCHECK_EQ(status_, UpdateStatus::IDLE);
458*5a923131SAndroid Build Coastguard Worker 
459*5a923131SAndroid Build Coastguard Worker   payload_fd_.reset(dup(fd));
460*5a923131SAndroid Build Coastguard Worker   const string payload_url = "fd://" + std::to_string(payload_fd_.get());
461*5a923131SAndroid Build Coastguard Worker 
462*5a923131SAndroid Build Coastguard Worker   return ApplyPayload(
463*5a923131SAndroid Build Coastguard Worker       payload_url, payload_offset, payload_size, key_value_pair_headers, error);
464*5a923131SAndroid Build Coastguard Worker }
465*5a923131SAndroid Build Coastguard Worker 
SuspendUpdate(Error * error)466*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::SuspendUpdate(Error* error) {
467*5a923131SAndroid Build Coastguard Worker   if (!processor_->IsRunning())
468*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
469*5a923131SAndroid Build Coastguard Worker         error, __LINE__, __FILE__, "No ongoing update to suspend.");
470*5a923131SAndroid Build Coastguard Worker   processor_->SuspendProcessing();
471*5a923131SAndroid Build Coastguard Worker   return true;
472*5a923131SAndroid Build Coastguard Worker }
473*5a923131SAndroid Build Coastguard Worker 
ResumeUpdate(Error * error)474*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::ResumeUpdate(Error* error) {
475*5a923131SAndroid Build Coastguard Worker   if (!processor_->IsRunning())
476*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
477*5a923131SAndroid Build Coastguard Worker         error, __LINE__, __FILE__, "No ongoing update to resume.");
478*5a923131SAndroid Build Coastguard Worker   processor_->ResumeProcessing();
479*5a923131SAndroid Build Coastguard Worker   return true;
480*5a923131SAndroid Build Coastguard Worker }
481*5a923131SAndroid Build Coastguard Worker 
CancelUpdate(Error * error)482*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::CancelUpdate(Error* error) {
483*5a923131SAndroid Build Coastguard Worker   if (!processor_->IsRunning())
484*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
485*5a923131SAndroid Build Coastguard Worker         error, __LINE__, __FILE__, "No ongoing update to cancel.");
486*5a923131SAndroid Build Coastguard Worker   processor_->StopProcessing();
487*5a923131SAndroid Build Coastguard Worker   return true;
488*5a923131SAndroid Build Coastguard Worker }
489*5a923131SAndroid Build Coastguard Worker 
ResetStatus(Error * error)490*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::ResetStatus(Error* error) {
491*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Attempting to reset state from "
492*5a923131SAndroid Build Coastguard Worker             << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
493*5a923131SAndroid Build Coastguard Worker   if (processor_->IsRunning()) {
494*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
495*5a923131SAndroid Build Coastguard Worker         error,
496*5a923131SAndroid Build Coastguard Worker         __LINE__,
497*5a923131SAndroid Build Coastguard Worker         __FILE__,
498*5a923131SAndroid Build Coastguard Worker         "Already processing an update, cancel it first.");
499*5a923131SAndroid Build Coastguard Worker   }
500*5a923131SAndroid Build Coastguard Worker   if (status_ != UpdateStatus::IDLE &&
501*5a923131SAndroid Build Coastguard Worker       status_ != UpdateStatus::UPDATED_NEED_REBOOT) {
502*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
503*5a923131SAndroid Build Coastguard Worker         error,
504*5a923131SAndroid Build Coastguard Worker         __LINE__,
505*5a923131SAndroid Build Coastguard Worker         __FILE__,
506*5a923131SAndroid Build Coastguard Worker         "Status reset not allowed in this state, please "
507*5a923131SAndroid Build Coastguard Worker         "cancel on going OTA first.");
508*5a923131SAndroid Build Coastguard Worker   }
509*5a923131SAndroid Build Coastguard Worker 
510*5a923131SAndroid Build Coastguard Worker   if (apex_handler_android_ != nullptr) {
511*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Cleaning up reserved space for compressed APEX (if any)";
512*5a923131SAndroid Build Coastguard Worker     std::vector<ApexInfo> apex_infos_blank;
513*5a923131SAndroid Build Coastguard Worker     apex_handler_android_->AllocateSpace(apex_infos_blank);
514*5a923131SAndroid Build Coastguard Worker   }
515*5a923131SAndroid Build Coastguard Worker   // Remove the reboot marker so that if the machine is rebooted
516*5a923131SAndroid Build Coastguard Worker   // after resetting to idle state, it doesn't go back to
517*5a923131SAndroid Build Coastguard Worker   // UpdateStatus::UPDATED_NEED_REBOOT state.
518*5a923131SAndroid Build Coastguard Worker   if (!ClearUpdateCompletedMarker()) {
519*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(error,
520*5a923131SAndroid Build Coastguard Worker                                  __LINE__,
521*5a923131SAndroid Build Coastguard Worker                                  __FILE__,
522*5a923131SAndroid Build Coastguard Worker                                  "Failed to reset the status because "
523*5a923131SAndroid Build Coastguard Worker                                  "ClearUpdateCompletedMarker() failed");
524*5a923131SAndroid Build Coastguard Worker   }
525*5a923131SAndroid Build Coastguard Worker   if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
526*5a923131SAndroid Build Coastguard Worker     if (!resetShouldSwitchSlotOnReboot(error)) {
527*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Failed to reset slot switch.";
528*5a923131SAndroid Build Coastguard Worker       return false;
529*5a923131SAndroid Build Coastguard Worker     }
530*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Slot switch reset successful";
531*5a923131SAndroid Build Coastguard Worker   }
532*5a923131SAndroid Build Coastguard Worker   if (!boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_)) {
533*5a923131SAndroid Build Coastguard Worker     LOG(WARNING) << "Failed to reset snapshots. UpdateStatus is IDLE but"
534*5a923131SAndroid Build Coastguard Worker                  << "space might not be freed.";
535*5a923131SAndroid Build Coastguard Worker   }
536*5a923131SAndroid Build Coastguard Worker   return true;
537*5a923131SAndroid Build Coastguard Worker }
538*5a923131SAndroid Build Coastguard Worker 
operator ==(const std::vector<unsigned char> & a,std::string_view b)539*5a923131SAndroid Build Coastguard Worker bool operator==(const std::vector<unsigned char>& a, std::string_view b) {
540*5a923131SAndroid Build Coastguard Worker   if (a.size() != b.size()) {
541*5a923131SAndroid Build Coastguard Worker     return false;
542*5a923131SAndroid Build Coastguard Worker   }
543*5a923131SAndroid Build Coastguard Worker   return memcmp(a.data(), b.data(), a.size()) == 0;
544*5a923131SAndroid Build Coastguard Worker }
operator !=(const std::vector<unsigned char> & a,std::string_view b)545*5a923131SAndroid Build Coastguard Worker bool operator!=(const std::vector<unsigned char>& a, std::string_view b) {
546*5a923131SAndroid Build Coastguard Worker   return !(a == b);
547*5a923131SAndroid Build Coastguard Worker }
548*5a923131SAndroid Build Coastguard Worker 
VerifyPayloadParseManifest(const std::string & metadata_filename,std::string_view expected_metadata_hash,DeltaArchiveManifest * manifest,Error * error)549*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::VerifyPayloadParseManifest(
550*5a923131SAndroid Build Coastguard Worker     const std::string& metadata_filename,
551*5a923131SAndroid Build Coastguard Worker     std::string_view expected_metadata_hash,
552*5a923131SAndroid Build Coastguard Worker     DeltaArchiveManifest* manifest,
553*5a923131SAndroid Build Coastguard Worker     Error* error) {
554*5a923131SAndroid Build Coastguard Worker   FileDescriptorPtr fd(new EintrSafeFileDescriptor);
555*5a923131SAndroid Build Coastguard Worker   if (!fd->Open(metadata_filename.c_str(), O_RDONLY)) {
556*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
557*5a923131SAndroid Build Coastguard Worker                           __LINE__,
558*5a923131SAndroid Build Coastguard Worker                           __FILE__,
559*5a923131SAndroid Build Coastguard Worker                           "Failed to open " + metadata_filename,
560*5a923131SAndroid Build Coastguard Worker                           ErrorCode::kDownloadManifestParseError);
561*5a923131SAndroid Build Coastguard Worker   }
562*5a923131SAndroid Build Coastguard Worker   brillo::Blob metadata(kMaxPayloadHeaderSize);
563*5a923131SAndroid Build Coastguard Worker   if (!fd->Read(metadata.data(), metadata.size())) {
564*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(
565*5a923131SAndroid Build Coastguard Worker         error,
566*5a923131SAndroid Build Coastguard Worker         __LINE__,
567*5a923131SAndroid Build Coastguard Worker         __FILE__,
568*5a923131SAndroid Build Coastguard Worker         "Failed to read payload header from " + metadata_filename,
569*5a923131SAndroid Build Coastguard Worker         ErrorCode::kDownloadManifestParseError);
570*5a923131SAndroid Build Coastguard Worker   }
571*5a923131SAndroid Build Coastguard Worker   ErrorCode errorcode{};
572*5a923131SAndroid Build Coastguard Worker   PayloadMetadata payload_metadata;
573*5a923131SAndroid Build Coastguard Worker   if (payload_metadata.ParsePayloadHeader(metadata, &errorcode) !=
574*5a923131SAndroid Build Coastguard Worker       MetadataParseResult::kSuccess) {
575*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
576*5a923131SAndroid Build Coastguard Worker                           __LINE__,
577*5a923131SAndroid Build Coastguard Worker                           __FILE__,
578*5a923131SAndroid Build Coastguard Worker                           "Failed to parse payload header: " +
579*5a923131SAndroid Build Coastguard Worker                               utils::ErrorCodeToString(errorcode),
580*5a923131SAndroid Build Coastguard Worker                           errorcode);
581*5a923131SAndroid Build Coastguard Worker   }
582*5a923131SAndroid Build Coastguard Worker   uint64_t metadata_size = payload_metadata.GetMetadataSize() +
583*5a923131SAndroid Build Coastguard Worker                            payload_metadata.GetMetadataSignatureSize();
584*5a923131SAndroid Build Coastguard Worker   if (metadata_size < kMaxPayloadHeaderSize ||
585*5a923131SAndroid Build Coastguard Worker       metadata_size >
586*5a923131SAndroid Build Coastguard Worker           static_cast<uint64_t>(utils::FileSize(metadata_filename))) {
587*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(
588*5a923131SAndroid Build Coastguard Worker         error,
589*5a923131SAndroid Build Coastguard Worker         __LINE__,
590*5a923131SAndroid Build Coastguard Worker         __FILE__,
591*5a923131SAndroid Build Coastguard Worker         "Invalid metadata size: " + std::to_string(metadata_size),
592*5a923131SAndroid Build Coastguard Worker         ErrorCode::kDownloadManifestParseError);
593*5a923131SAndroid Build Coastguard Worker   }
594*5a923131SAndroid Build Coastguard Worker   metadata.resize(metadata_size);
595*5a923131SAndroid Build Coastguard Worker   if (!fd->Read(metadata.data() + kMaxPayloadHeaderSize,
596*5a923131SAndroid Build Coastguard Worker                 metadata.size() - kMaxPayloadHeaderSize)) {
597*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(
598*5a923131SAndroid Build Coastguard Worker         error,
599*5a923131SAndroid Build Coastguard Worker         __LINE__,
600*5a923131SAndroid Build Coastguard Worker         __FILE__,
601*5a923131SAndroid Build Coastguard Worker         "Failed to read metadata and signature from " + metadata_filename,
602*5a923131SAndroid Build Coastguard Worker         ErrorCode::kDownloadManifestParseError);
603*5a923131SAndroid Build Coastguard Worker   }
604*5a923131SAndroid Build Coastguard Worker   fd->Close();
605*5a923131SAndroid Build Coastguard Worker   if (!expected_metadata_hash.empty()) {
606*5a923131SAndroid Build Coastguard Worker     brillo::Blob metadata_hash;
607*5a923131SAndroid Build Coastguard Worker     TEST_AND_RETURN_FALSE(HashCalculator::RawHashOfBytes(
608*5a923131SAndroid Build Coastguard Worker         metadata.data(), payload_metadata.GetMetadataSize(), &metadata_hash));
609*5a923131SAndroid Build Coastguard Worker     if (metadata_hash != expected_metadata_hash) {
610*5a923131SAndroid Build Coastguard Worker       return LogAndSetError(error,
611*5a923131SAndroid Build Coastguard Worker                             __LINE__,
612*5a923131SAndroid Build Coastguard Worker                             __FILE__,
613*5a923131SAndroid Build Coastguard Worker                             "Metadata hash mismatch. Expected hash: " +
614*5a923131SAndroid Build Coastguard Worker                                 HexEncode(expected_metadata_hash) +
615*5a923131SAndroid Build Coastguard Worker                                 " actual hash: " + HexEncode(metadata_hash),
616*5a923131SAndroid Build Coastguard Worker                             ErrorCode::kDownloadManifestParseError);
617*5a923131SAndroid Build Coastguard Worker     } else {
618*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Payload metadata hash check passed : "
619*5a923131SAndroid Build Coastguard Worker                 << HexEncode(metadata_hash);
620*5a923131SAndroid Build Coastguard Worker     }
621*5a923131SAndroid Build Coastguard Worker   }
622*5a923131SAndroid Build Coastguard Worker 
623*5a923131SAndroid Build Coastguard Worker   auto payload_verifier = PayloadVerifier::CreateInstanceFromZipPath(
624*5a923131SAndroid Build Coastguard Worker       constants::kUpdateCertificatesPath);
625*5a923131SAndroid Build Coastguard Worker   if (!payload_verifier) {
626*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
627*5a923131SAndroid Build Coastguard Worker                           __LINE__,
628*5a923131SAndroid Build Coastguard Worker                           __FILE__,
629*5a923131SAndroid Build Coastguard Worker                           "Failed to create the payload verifier from " +
630*5a923131SAndroid Build Coastguard Worker                               std::string(constants::kUpdateCertificatesPath),
631*5a923131SAndroid Build Coastguard Worker                           ErrorCode::kDownloadManifestParseError);
632*5a923131SAndroid Build Coastguard Worker   }
633*5a923131SAndroid Build Coastguard Worker   errorcode = payload_metadata.ValidateMetadataSignature(
634*5a923131SAndroid Build Coastguard Worker       metadata, "", *payload_verifier);
635*5a923131SAndroid Build Coastguard Worker   if (errorcode != ErrorCode::kSuccess) {
636*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
637*5a923131SAndroid Build Coastguard Worker                           __LINE__,
638*5a923131SAndroid Build Coastguard Worker                           __FILE__,
639*5a923131SAndroid Build Coastguard Worker                           "Failed to validate metadata signature: " +
640*5a923131SAndroid Build Coastguard Worker                               utils::ErrorCodeToString(errorcode),
641*5a923131SAndroid Build Coastguard Worker                           errorcode);
642*5a923131SAndroid Build Coastguard Worker   }
643*5a923131SAndroid Build Coastguard Worker   if (!payload_metadata.GetManifest(metadata, manifest)) {
644*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(error,
645*5a923131SAndroid Build Coastguard Worker                           __LINE__,
646*5a923131SAndroid Build Coastguard Worker                           __FILE__,
647*5a923131SAndroid Build Coastguard Worker                           "Failed to parse manifest.",
648*5a923131SAndroid Build Coastguard Worker                           ErrorCode::kDownloadManifestParseError);
649*5a923131SAndroid Build Coastguard Worker   }
650*5a923131SAndroid Build Coastguard Worker 
651*5a923131SAndroid Build Coastguard Worker   return true;
652*5a923131SAndroid Build Coastguard Worker }
653*5a923131SAndroid Build Coastguard Worker 
VerifyPayloadApplicable(const std::string & metadata_filename,Error * error)654*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::VerifyPayloadApplicable(
655*5a923131SAndroid Build Coastguard Worker     const std::string& metadata_filename, Error* error) {
656*5a923131SAndroid Build Coastguard Worker   DeltaArchiveManifest manifest;
657*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(
658*5a923131SAndroid Build Coastguard Worker       VerifyPayloadParseManifest(metadata_filename, &manifest, error));
659*5a923131SAndroid Build Coastguard Worker 
660*5a923131SAndroid Build Coastguard Worker   FileDescriptorPtr fd(new EintrSafeFileDescriptor);
661*5a923131SAndroid Build Coastguard Worker   ErrorCode errorcode{};
662*5a923131SAndroid Build Coastguard Worker 
663*5a923131SAndroid Build Coastguard Worker   BootControlInterface::Slot current_slot = GetCurrentSlot();
664*5a923131SAndroid Build Coastguard Worker   if (current_slot < 0) {
665*5a923131SAndroid Build Coastguard Worker     return LogAndSetError(
666*5a923131SAndroid Build Coastguard Worker         error,
667*5a923131SAndroid Build Coastguard Worker         __LINE__,
668*5a923131SAndroid Build Coastguard Worker         __FILE__,
669*5a923131SAndroid Build Coastguard Worker         "Failed to get current slot " + std::to_string(current_slot),
670*5a923131SAndroid Build Coastguard Worker         ErrorCode::kDownloadStateInitializationError);
671*5a923131SAndroid Build Coastguard Worker   }
672*5a923131SAndroid Build Coastguard Worker   for (const PartitionUpdate& partition : manifest.partitions()) {
673*5a923131SAndroid Build Coastguard Worker     if (!partition.has_old_partition_info())
674*5a923131SAndroid Build Coastguard Worker       continue;
675*5a923131SAndroid Build Coastguard Worker     string partition_path;
676*5a923131SAndroid Build Coastguard Worker     if (!boot_control_->GetPartitionDevice(
677*5a923131SAndroid Build Coastguard Worker             partition.partition_name(), current_slot, &partition_path)) {
678*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(
679*5a923131SAndroid Build Coastguard Worker           error,
680*5a923131SAndroid Build Coastguard Worker           __LINE__,
681*5a923131SAndroid Build Coastguard Worker           __FILE__,
682*5a923131SAndroid Build Coastguard Worker           "Failed to get partition device for " + partition.partition_name());
683*5a923131SAndroid Build Coastguard Worker     }
684*5a923131SAndroid Build Coastguard Worker     if (!fd->Open(partition_path.c_str(), O_RDONLY)) {
685*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(
686*5a923131SAndroid Build Coastguard Worker           error, __LINE__, __FILE__, "Failed to open " + partition_path);
687*5a923131SAndroid Build Coastguard Worker     }
688*5a923131SAndroid Build Coastguard Worker     for (const InstallOperation& operation : partition.operations()) {
689*5a923131SAndroid Build Coastguard Worker       if (!operation.has_src_sha256_hash())
690*5a923131SAndroid Build Coastguard Worker         continue;
691*5a923131SAndroid Build Coastguard Worker       brillo::Blob source_hash;
692*5a923131SAndroid Build Coastguard Worker       if (!fd_utils::ReadAndHashExtents(fd,
693*5a923131SAndroid Build Coastguard Worker                                         operation.src_extents(),
694*5a923131SAndroid Build Coastguard Worker                                         manifest.block_size(),
695*5a923131SAndroid Build Coastguard Worker                                         &source_hash)) {
696*5a923131SAndroid Build Coastguard Worker         return LogAndSetGenericError(
697*5a923131SAndroid Build Coastguard Worker             error, __LINE__, __FILE__, "Failed to hash " + partition_path);
698*5a923131SAndroid Build Coastguard Worker       }
699*5a923131SAndroid Build Coastguard Worker       if (!PartitionWriter::ValidateSourceHash(
700*5a923131SAndroid Build Coastguard Worker               source_hash, operation, fd, &errorcode)) {
701*5a923131SAndroid Build Coastguard Worker         return false;
702*5a923131SAndroid Build Coastguard Worker       }
703*5a923131SAndroid Build Coastguard Worker     }
704*5a923131SAndroid Build Coastguard Worker     fd->Close();
705*5a923131SAndroid Build Coastguard Worker   }
706*5a923131SAndroid Build Coastguard Worker   return true;
707*5a923131SAndroid Build Coastguard Worker }
708*5a923131SAndroid Build Coastguard Worker 
ProcessingDone(const ActionProcessor * processor,ErrorCode code)709*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
710*5a923131SAndroid Build Coastguard Worker                                             ErrorCode code) {
711*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Processing Done.";
712*5a923131SAndroid Build Coastguard Worker   metric_bytes_downloaded_.Flush(true);
713*5a923131SAndroid Build Coastguard Worker   metric_total_bytes_downloaded_.Flush(true);
714*5a923131SAndroid Build Coastguard Worker   if (status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE) {
715*5a923131SAndroid Build Coastguard Worker     TerminateUpdateAndNotify(code);
716*5a923131SAndroid Build Coastguard Worker     return;
717*5a923131SAndroid Build Coastguard Worker   }
718*5a923131SAndroid Build Coastguard Worker 
719*5a923131SAndroid Build Coastguard Worker   switch (code) {
720*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kSuccess:
721*5a923131SAndroid Build Coastguard Worker       // Update succeeded.
722*5a923131SAndroid Build Coastguard Worker       if (!WriteUpdateCompletedMarker()) {
723*5a923131SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to write update completion marker";
724*5a923131SAndroid Build Coastguard Worker       }
725*5a923131SAndroid Build Coastguard Worker       prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
726*5a923131SAndroid Build Coastguard Worker 
727*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Update successfully applied, waiting to reboot.";
728*5a923131SAndroid Build Coastguard Worker       break;
729*5a923131SAndroid Build Coastguard Worker 
730*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kFilesystemCopierError:
731*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kNewRootfsVerificationError:
732*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kNewKernelVerificationError:
733*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kFilesystemVerifierError:
734*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kDownloadStateInitializationError:
735*5a923131SAndroid Build Coastguard Worker       // Reset the ongoing update for these errors so it starts from the
736*5a923131SAndroid Build Coastguard Worker       // beginning next time.
737*5a923131SAndroid Build Coastguard Worker       DeltaPerformer::ResetUpdateProgress(prefs_, false);
738*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Resetting update progress.";
739*5a923131SAndroid Build Coastguard Worker       break;
740*5a923131SAndroid Build Coastguard Worker 
741*5a923131SAndroid Build Coastguard Worker     case ErrorCode::kPayloadTimestampError:
742*5a923131SAndroid Build Coastguard Worker       // SafetyNet logging, b/36232423
743*5a923131SAndroid Build Coastguard Worker       android_errorWriteLog(0x534e4554, "36232423");
744*5a923131SAndroid Build Coastguard Worker       break;
745*5a923131SAndroid Build Coastguard Worker 
746*5a923131SAndroid Build Coastguard Worker     default:
747*5a923131SAndroid Build Coastguard Worker       // Ignore all other error codes.
748*5a923131SAndroid Build Coastguard Worker       break;
749*5a923131SAndroid Build Coastguard Worker   }
750*5a923131SAndroid Build Coastguard Worker 
751*5a923131SAndroid Build Coastguard Worker   TerminateUpdateAndNotify(code);
752*5a923131SAndroid Build Coastguard Worker }
753*5a923131SAndroid Build Coastguard Worker 
ProcessingStopped(const ActionProcessor * processor)754*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ProcessingStopped(
755*5a923131SAndroid Build Coastguard Worker     const ActionProcessor* processor) {
756*5a923131SAndroid Build Coastguard Worker   TerminateUpdateAndNotify(ErrorCode::kUserCanceled);
757*5a923131SAndroid Build Coastguard Worker }
758*5a923131SAndroid Build Coastguard Worker 
ActionCompleted(ActionProcessor * processor,AbstractAction * action,ErrorCode code)759*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor,
760*5a923131SAndroid Build Coastguard Worker                                              AbstractAction* action,
761*5a923131SAndroid Build Coastguard Worker                                              ErrorCode code) {
762*5a923131SAndroid Build Coastguard Worker   // Reset download progress regardless of whether or not the download
763*5a923131SAndroid Build Coastguard Worker   // action succeeded.
764*5a923131SAndroid Build Coastguard Worker   const string type = action->Type();
765*5a923131SAndroid Build Coastguard Worker   if (type == CleanupPreviousUpdateAction::StaticType() ||
766*5a923131SAndroid Build Coastguard Worker       (type == NoOpAction::StaticType() &&
767*5a923131SAndroid Build Coastguard Worker        status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE)) {
768*5a923131SAndroid Build Coastguard Worker     cleanup_previous_update_code_ = code;
769*5a923131SAndroid Build Coastguard Worker     NotifyCleanupPreviousUpdateCallbacksAndClear();
770*5a923131SAndroid Build Coastguard Worker   }
771*5a923131SAndroid Build Coastguard Worker   // download_progress_ is actually used by other actions, such as
772*5a923131SAndroid Build Coastguard Worker   // filesystem_verify_action. Therefore we always clear it.
773*5a923131SAndroid Build Coastguard Worker   download_progress_ = 0;
774*5a923131SAndroid Build Coastguard Worker   if (type == PostinstallRunnerAction::StaticType()) {
775*5a923131SAndroid Build Coastguard Worker     bool succeeded =
776*5a923131SAndroid Build Coastguard Worker         code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive;
777*5a923131SAndroid Build Coastguard Worker     prefs_->SetBoolean(kPrefsPostInstallSucceeded, succeeded);
778*5a923131SAndroid Build Coastguard Worker   }
779*5a923131SAndroid Build Coastguard Worker   if (code != ErrorCode::kSuccess) {
780*5a923131SAndroid Build Coastguard Worker     // If an action failed, the ActionProcessor will cancel the whole thing.
781*5a923131SAndroid Build Coastguard Worker     return;
782*5a923131SAndroid Build Coastguard Worker   }
783*5a923131SAndroid Build Coastguard Worker   if (type == UpdateBootFlagsAction::StaticType()) {
784*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::CLEANUP_PREVIOUS_UPDATE);
785*5a923131SAndroid Build Coastguard Worker   }
786*5a923131SAndroid Build Coastguard Worker   if (type == DownloadAction::StaticType()) {
787*5a923131SAndroid Build Coastguard Worker     auto download_action = static_cast<DownloadAction*>(action);
788*5a923131SAndroid Build Coastguard Worker     install_plan_ = *download_action->install_plan();
789*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::VERIFYING);
790*5a923131SAndroid Build Coastguard Worker   } else if (type == FilesystemVerifierAction::StaticType()) {
791*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::FINALIZING);
792*5a923131SAndroid Build Coastguard Worker     prefs_->SetBoolean(kPrefsVerityWritten, true);
793*5a923131SAndroid Build Coastguard Worker   }
794*5a923131SAndroid Build Coastguard Worker }
795*5a923131SAndroid Build Coastguard Worker 
BytesReceived(uint64_t bytes_progressed,uint64_t bytes_received,uint64_t total)796*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed,
797*5a923131SAndroid Build Coastguard Worker                                            uint64_t bytes_received,
798*5a923131SAndroid Build Coastguard Worker                                            uint64_t total) {
799*5a923131SAndroid Build Coastguard Worker   double progress = 0;
800*5a923131SAndroid Build Coastguard Worker   if (total)
801*5a923131SAndroid Build Coastguard Worker     progress = static_cast<double>(bytes_received) / static_cast<double>(total);
802*5a923131SAndroid Build Coastguard Worker   if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) {
803*5a923131SAndroid Build Coastguard Worker     download_progress_ = progress;
804*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::DOWNLOADING);
805*5a923131SAndroid Build Coastguard Worker   } else {
806*5a923131SAndroid Build Coastguard Worker     ProgressUpdate(progress);
807*5a923131SAndroid Build Coastguard Worker   }
808*5a923131SAndroid Build Coastguard Worker 
809*5a923131SAndroid Build Coastguard Worker   // Update the bytes downloaded in prefs.
810*5a923131SAndroid Build Coastguard Worker   metric_bytes_downloaded_ += bytes_progressed;
811*5a923131SAndroid Build Coastguard Worker   metric_total_bytes_downloaded_ += bytes_progressed;
812*5a923131SAndroid Build Coastguard Worker }
813*5a923131SAndroid Build Coastguard Worker 
ShouldCancel(ErrorCode * cancel_reason)814*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
815*5a923131SAndroid Build Coastguard Worker   // TODO(deymo): Notify the DownloadAction that it should cancel the update
816*5a923131SAndroid Build Coastguard Worker   // download.
817*5a923131SAndroid Build Coastguard Worker   return false;
818*5a923131SAndroid Build Coastguard Worker }
819*5a923131SAndroid Build Coastguard Worker 
DownloadComplete()820*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::DownloadComplete() {
821*5a923131SAndroid Build Coastguard Worker   // Nothing needs to be done when the download completes.
822*5a923131SAndroid Build Coastguard Worker }
823*5a923131SAndroid Build Coastguard Worker 
ProgressUpdate(double progress)824*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ProgressUpdate(double progress) {
825*5a923131SAndroid Build Coastguard Worker   // Self throttle based on progress. Also send notifications if progress is
826*5a923131SAndroid Build Coastguard Worker   // too slow.
827*5a923131SAndroid Build Coastguard Worker   if (progress == 1.0 ||
828*5a923131SAndroid Build Coastguard Worker       progress - download_progress_ >= kBroadcastThresholdProgress ||
829*5a923131SAndroid Build Coastguard Worker       TimeTicks::Now() - last_notify_time_ >=
830*5a923131SAndroid Build Coastguard Worker           TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) {
831*5a923131SAndroid Build Coastguard Worker     download_progress_ = progress;
832*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(status_);
833*5a923131SAndroid Build Coastguard Worker   }
834*5a923131SAndroid Build Coastguard Worker }
835*5a923131SAndroid Build Coastguard Worker 
OnVerifyProgressUpdate(double progress)836*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::OnVerifyProgressUpdate(double progress) {
837*5a923131SAndroid Build Coastguard Worker   assert(status_ == UpdateStatus::VERIFYING);
838*5a923131SAndroid Build Coastguard Worker   ProgressUpdate(progress);
839*5a923131SAndroid Build Coastguard Worker }
840*5a923131SAndroid Build Coastguard Worker 
ScheduleProcessingStart()841*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ScheduleProcessingStart() {
842*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Scheduling an action processor start.";
843*5a923131SAndroid Build Coastguard Worker   processor_->set_delegate(this);
844*5a923131SAndroid Build Coastguard Worker   brillo::MessageLoop::current()->PostTask(
845*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
846*5a923131SAndroid Build Coastguard Worker       Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
847*5a923131SAndroid Build Coastguard Worker            base::Unretained(processor_.get())));
848*5a923131SAndroid Build Coastguard Worker }
849*5a923131SAndroid Build Coastguard Worker 
TerminateUpdateAndNotify(ErrorCode error_code)850*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
851*5a923131SAndroid Build Coastguard Worker   if (status_ == UpdateStatus::IDLE) {
852*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called.";
853*5a923131SAndroid Build Coastguard Worker     return;
854*5a923131SAndroid Build Coastguard Worker   }
855*5a923131SAndroid Build Coastguard Worker 
856*5a923131SAndroid Build Coastguard Worker   if (status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE) {
857*5a923131SAndroid Build Coastguard Worker     ClearUpdateCompletedMarker();
858*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Terminating cleanup previous update.";
859*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::IDLE);
860*5a923131SAndroid Build Coastguard Worker     for (auto observer : daemon_state_->service_observers())
861*5a923131SAndroid Build Coastguard Worker       observer->SendPayloadApplicationComplete(error_code);
862*5a923131SAndroid Build Coastguard Worker     return;
863*5a923131SAndroid Build Coastguard Worker   }
864*5a923131SAndroid Build Coastguard Worker 
865*5a923131SAndroid Build Coastguard Worker   boot_control_->GetDynamicPartitionControl()->Cleanup();
866*5a923131SAndroid Build Coastguard Worker 
867*5a923131SAndroid Build Coastguard Worker   for (auto observer : daemon_state_->service_observers())
868*5a923131SAndroid Build Coastguard Worker     observer->SendPayloadApplicationComplete(error_code);
869*5a923131SAndroid Build Coastguard Worker 
870*5a923131SAndroid Build Coastguard Worker   download_progress_ = 0;
871*5a923131SAndroid Build Coastguard Worker   UpdateStatus new_status =
872*5a923131SAndroid Build Coastguard Worker       (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
873*5a923131SAndroid Build Coastguard Worker                                          : UpdateStatus::IDLE);
874*5a923131SAndroid Build Coastguard Worker   SetStatusAndNotify(new_status);
875*5a923131SAndroid Build Coastguard Worker   payload_fd_.reset();
876*5a923131SAndroid Build Coastguard Worker 
877*5a923131SAndroid Build Coastguard Worker   // The network id is only applicable to one download attempt and once it's
878*5a923131SAndroid Build Coastguard Worker   // done the network id should not be re-used anymore.
879*5a923131SAndroid Build Coastguard Worker   if (!network_selector_->SetProcessNetwork(kDefaultNetworkId)) {
880*5a923131SAndroid Build Coastguard Worker     LOG(WARNING) << "Unable to unbind network.";
881*5a923131SAndroid Build Coastguard Worker   }
882*5a923131SAndroid Build Coastguard Worker 
883*5a923131SAndroid Build Coastguard Worker   CollectAndReportUpdateMetricsOnUpdateFinished(error_code);
884*5a923131SAndroid Build Coastguard Worker   ClearMetricsPrefs();
885*5a923131SAndroid Build Coastguard Worker   if (error_code == ErrorCode::kSuccess) {
886*5a923131SAndroid Build Coastguard Worker     // We should only reset the PayloadAttemptNumber if the update succeeds, or
887*5a923131SAndroid Build Coastguard Worker     // we switch to a different payload.
888*5a923131SAndroid Build Coastguard Worker     prefs_->Delete(kPrefsPayloadAttemptNumber);
889*5a923131SAndroid Build Coastguard Worker     metrics_utils::SetSystemUpdatedMarker(clock_.get(), prefs_);
890*5a923131SAndroid Build Coastguard Worker     // Clear the total bytes downloaded if and only if the update succeeds.
891*5a923131SAndroid Build Coastguard Worker     metric_total_bytes_downloaded_.Delete();
892*5a923131SAndroid Build Coastguard Worker   }
893*5a923131SAndroid Build Coastguard Worker }
894*5a923131SAndroid Build Coastguard Worker 
SetStatusAndNotify(UpdateStatus status)895*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
896*5a923131SAndroid Build Coastguard Worker   status_ = status;
897*5a923131SAndroid Build Coastguard Worker   size_t payload_size =
898*5a923131SAndroid Build Coastguard Worker       install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size;
899*5a923131SAndroid Build Coastguard Worker   UpdateEngineStatus status_to_send = {.status = status_,
900*5a923131SAndroid Build Coastguard Worker                                        .progress = download_progress_,
901*5a923131SAndroid Build Coastguard Worker                                        .new_size_bytes = payload_size};
902*5a923131SAndroid Build Coastguard Worker 
903*5a923131SAndroid Build Coastguard Worker   for (auto observer : daemon_state_->service_observers()) {
904*5a923131SAndroid Build Coastguard Worker     observer->SendStatusUpdate(status_to_send);
905*5a923131SAndroid Build Coastguard Worker   }
906*5a923131SAndroid Build Coastguard Worker   last_notify_time_ = TimeTicks::Now();
907*5a923131SAndroid Build Coastguard Worker }
908*5a923131SAndroid Build Coastguard Worker 
BuildUpdateActions(HttpFetcher * fetcher)909*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::BuildUpdateActions(HttpFetcher* fetcher) {
910*5a923131SAndroid Build Coastguard Worker   CHECK(!processor_->IsRunning());
911*5a923131SAndroid Build Coastguard Worker 
912*5a923131SAndroid Build Coastguard Worker   // Actions:
913*5a923131SAndroid Build Coastguard Worker   auto update_boot_flags_action =
914*5a923131SAndroid Build Coastguard Worker       std::make_unique<UpdateBootFlagsAction>(boot_control_);
915*5a923131SAndroid Build Coastguard Worker   auto cleanup_previous_update_action =
916*5a923131SAndroid Build Coastguard Worker       boot_control_->GetDynamicPartitionControl()
917*5a923131SAndroid Build Coastguard Worker           ->GetCleanupPreviousUpdateAction(boot_control_, prefs_, this);
918*5a923131SAndroid Build Coastguard Worker   auto install_plan_action = std::make_unique<InstallPlanAction>(install_plan_);
919*5a923131SAndroid Build Coastguard Worker   auto download_action =
920*5a923131SAndroid Build Coastguard Worker       std::make_unique<DownloadAction>(prefs_,
921*5a923131SAndroid Build Coastguard Worker                                        boot_control_,
922*5a923131SAndroid Build Coastguard Worker                                        hardware_,
923*5a923131SAndroid Build Coastguard Worker                                        fetcher,  // passes ownership
924*5a923131SAndroid Build Coastguard Worker                                        true /* interactive */,
925*5a923131SAndroid Build Coastguard Worker                                        update_certificates_path_);
926*5a923131SAndroid Build Coastguard Worker   download_action->set_delegate(this);
927*5a923131SAndroid Build Coastguard Worker   download_action->set_base_offset(base_offset_);
928*5a923131SAndroid Build Coastguard Worker   auto filesystem_verifier_action = std::make_unique<FilesystemVerifierAction>(
929*5a923131SAndroid Build Coastguard Worker       boot_control_->GetDynamicPartitionControl());
930*5a923131SAndroid Build Coastguard Worker   auto postinstall_runner_action =
931*5a923131SAndroid Build Coastguard Worker       std::make_unique<PostinstallRunnerAction>(boot_control_, hardware_);
932*5a923131SAndroid Build Coastguard Worker   filesystem_verifier_action->set_delegate(this);
933*5a923131SAndroid Build Coastguard Worker   postinstall_runner_action->set_delegate(this);
934*5a923131SAndroid Build Coastguard Worker 
935*5a923131SAndroid Build Coastguard Worker   // Bond them together. We have to use the leaf-types when calling
936*5a923131SAndroid Build Coastguard Worker   // BondActions().
937*5a923131SAndroid Build Coastguard Worker   BondActions(install_plan_action.get(), download_action.get());
938*5a923131SAndroid Build Coastguard Worker   BondActions(download_action.get(), filesystem_verifier_action.get());
939*5a923131SAndroid Build Coastguard Worker   BondActions(filesystem_verifier_action.get(),
940*5a923131SAndroid Build Coastguard Worker               postinstall_runner_action.get());
941*5a923131SAndroid Build Coastguard Worker 
942*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(update_boot_flags_action));
943*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(cleanup_previous_update_action));
944*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(install_plan_action));
945*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(download_action));
946*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(filesystem_verifier_action));
947*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(postinstall_runner_action));
948*5a923131SAndroid Build Coastguard Worker }
949*5a923131SAndroid Build Coastguard Worker 
WriteUpdateCompletedMarker()950*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
951*5a923131SAndroid Build Coastguard Worker   string boot_id;
952*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
953*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Writing update complete marker, slot "
954*5a923131SAndroid Build Coastguard Worker             << boot_control_->GetCurrentSlot() << ", boot id: " << boot_id;
955*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(
956*5a923131SAndroid Build Coastguard Worker       prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id));
957*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(
958*5a923131SAndroid Build Coastguard Worker       prefs_->SetInt64(kPrefsPreviousSlot, boot_control_->GetCurrentSlot()));
959*5a923131SAndroid Build Coastguard Worker   return true;
960*5a923131SAndroid Build Coastguard Worker }
961*5a923131SAndroid Build Coastguard Worker 
ClearUpdateCompletedMarker()962*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::ClearUpdateCompletedMarker() {
963*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Clearing update complete marker.";
964*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(prefs_->Delete(kPrefsUpdateCompletedOnBootId));
965*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(prefs_->Delete(kPrefsPreviousSlot));
966*5a923131SAndroid Build Coastguard Worker   return true;
967*5a923131SAndroid Build Coastguard Worker }
968*5a923131SAndroid Build Coastguard Worker 
UpdateCompletedOnThisBoot() const969*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() const {
970*5a923131SAndroid Build Coastguard Worker   // In case of an update_engine restart without a reboot, we stored the boot_id
971*5a923131SAndroid Build Coastguard Worker   // when the update was completed by setting a pref, so we can check whether
972*5a923131SAndroid Build Coastguard Worker   // the last update was on this boot or a previous one.
973*5a923131SAndroid Build Coastguard Worker   string boot_id;
974*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
975*5a923131SAndroid Build Coastguard Worker 
976*5a923131SAndroid Build Coastguard Worker   string update_completed_on_boot_id;
977*5a923131SAndroid Build Coastguard Worker   return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
978*5a923131SAndroid Build Coastguard Worker           prefs_->GetString(kPrefsUpdateCompletedOnBootId,
979*5a923131SAndroid Build Coastguard Worker                             &update_completed_on_boot_id) &&
980*5a923131SAndroid Build Coastguard Worker           update_completed_on_boot_id == boot_id);
981*5a923131SAndroid Build Coastguard Worker }
982*5a923131SAndroid Build Coastguard Worker 
983*5a923131SAndroid Build Coastguard Worker // Collect and report the android metrics when we terminate the update.
CollectAndReportUpdateMetricsOnUpdateFinished(ErrorCode error_code)984*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::CollectAndReportUpdateMetricsOnUpdateFinished(
985*5a923131SAndroid Build Coastguard Worker     ErrorCode error_code) {
986*5a923131SAndroid Build Coastguard Worker   int64_t attempt_number =
987*5a923131SAndroid Build Coastguard Worker       metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
988*5a923131SAndroid Build Coastguard Worker   PayloadType payload_type = kPayloadTypeFull;
989*5a923131SAndroid Build Coastguard Worker   int64_t payload_size = 0;
990*5a923131SAndroid Build Coastguard Worker   for (const auto& p : install_plan_.payloads) {
991*5a923131SAndroid Build Coastguard Worker     if (p.type == InstallPayloadType::kDelta)
992*5a923131SAndroid Build Coastguard Worker       payload_type = kPayloadTypeDelta;
993*5a923131SAndroid Build Coastguard Worker     payload_size += p.size;
994*5a923131SAndroid Build Coastguard Worker   }
995*5a923131SAndroid Build Coastguard Worker   // In some cases, e.g. after calling |setShouldSwitchSlotOnReboot()|,  this
996*5a923131SAndroid Build Coastguard Worker   // function will be triggered, but payload_size in this case might be 0, if so
997*5a923131SAndroid Build Coastguard Worker   // skip reporting any metrics.
998*5a923131SAndroid Build Coastguard Worker   if (payload_size == 0) {
999*5a923131SAndroid Build Coastguard Worker     return;
1000*5a923131SAndroid Build Coastguard Worker   }
1001*5a923131SAndroid Build Coastguard Worker 
1002*5a923131SAndroid Build Coastguard Worker   metrics::AttemptResult attempt_result =
1003*5a923131SAndroid Build Coastguard Worker       metrics_utils::GetAttemptResult(error_code);
1004*5a923131SAndroid Build Coastguard Worker   Time boot_time_start = Time::FromInternalValue(
1005*5a923131SAndroid Build Coastguard Worker       metrics_utils::GetPersistedValue(kPrefsUpdateBootTimestampStart, prefs_));
1006*5a923131SAndroid Build Coastguard Worker   Time monotonic_time_start = Time::FromInternalValue(
1007*5a923131SAndroid Build Coastguard Worker       metrics_utils::GetPersistedValue(kPrefsUpdateTimestampStart, prefs_));
1008*5a923131SAndroid Build Coastguard Worker   TimeDelta duration = clock_->GetBootTime() - boot_time_start;
1009*5a923131SAndroid Build Coastguard Worker   TimeDelta duration_uptime = clock_->GetMonotonicTime() - monotonic_time_start;
1010*5a923131SAndroid Build Coastguard Worker 
1011*5a923131SAndroid Build Coastguard Worker   metrics_reporter_->ReportUpdateAttemptMetrics(
1012*5a923131SAndroid Build Coastguard Worker       static_cast<int>(attempt_number),
1013*5a923131SAndroid Build Coastguard Worker       payload_type,
1014*5a923131SAndroid Build Coastguard Worker       duration,
1015*5a923131SAndroid Build Coastguard Worker       duration_uptime,
1016*5a923131SAndroid Build Coastguard Worker       payload_size,
1017*5a923131SAndroid Build Coastguard Worker       attempt_result,
1018*5a923131SAndroid Build Coastguard Worker       error_code);
1019*5a923131SAndroid Build Coastguard Worker 
1020*5a923131SAndroid Build Coastguard Worker   int64_t current_bytes_downloaded = metric_bytes_downloaded_.get();
1021*5a923131SAndroid Build Coastguard Worker   metrics_reporter_->ReportUpdateAttemptDownloadMetrics(
1022*5a923131SAndroid Build Coastguard Worker       current_bytes_downloaded,
1023*5a923131SAndroid Build Coastguard Worker       0,
1024*5a923131SAndroid Build Coastguard Worker       DownloadSource::kNumDownloadSources,
1025*5a923131SAndroid Build Coastguard Worker       metrics::DownloadErrorCode::kUnset,
1026*5a923131SAndroid Build Coastguard Worker       metrics::ConnectionType::kUnset);
1027*5a923131SAndroid Build Coastguard Worker 
1028*5a923131SAndroid Build Coastguard Worker   if (error_code == ErrorCode::kSuccess) {
1029*5a923131SAndroid Build Coastguard Worker     int64_t reboot_count =
1030*5a923131SAndroid Build Coastguard Worker         metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
1031*5a923131SAndroid Build Coastguard Worker     string build_version;
1032*5a923131SAndroid Build Coastguard Worker     prefs_->GetString(kPrefsPreviousVersion, &build_version);
1033*5a923131SAndroid Build Coastguard Worker 
1034*5a923131SAndroid Build Coastguard Worker     // For android metrics, we only care about the total bytes downloaded
1035*5a923131SAndroid Build Coastguard Worker     // for all sources; for now we assume the only download source is
1036*5a923131SAndroid Build Coastguard Worker     // HttpsServer.
1037*5a923131SAndroid Build Coastguard Worker     int64_t total_bytes_downloaded = metric_total_bytes_downloaded_.get();
1038*5a923131SAndroid Build Coastguard Worker     int64_t num_bytes_downloaded[kNumDownloadSources] = {};
1039*5a923131SAndroid Build Coastguard Worker     num_bytes_downloaded[DownloadSource::kDownloadSourceHttpsServer] =
1040*5a923131SAndroid Build Coastguard Worker         total_bytes_downloaded;
1041*5a923131SAndroid Build Coastguard Worker 
1042*5a923131SAndroid Build Coastguard Worker     int download_overhead_percentage = 0;
1043*5a923131SAndroid Build Coastguard Worker     if (total_bytes_downloaded >= payload_size) {
1044*5a923131SAndroid Build Coastguard Worker       CHECK_GT(payload_size, 0);
1045*5a923131SAndroid Build Coastguard Worker       download_overhead_percentage =
1046*5a923131SAndroid Build Coastguard Worker           (total_bytes_downloaded - payload_size) * 100ull / payload_size;
1047*5a923131SAndroid Build Coastguard Worker     } else {
1048*5a923131SAndroid Build Coastguard Worker       LOG(WARNING) << "Downloaded bytes " << total_bytes_downloaded
1049*5a923131SAndroid Build Coastguard Worker                    << " is smaller than the payload size " << payload_size;
1050*5a923131SAndroid Build Coastguard Worker     }
1051*5a923131SAndroid Build Coastguard Worker 
1052*5a923131SAndroid Build Coastguard Worker     metrics_reporter_->ReportSuccessfulUpdateMetrics(
1053*5a923131SAndroid Build Coastguard Worker         static_cast<int>(attempt_number),
1054*5a923131SAndroid Build Coastguard Worker         0,  // update abandoned count
1055*5a923131SAndroid Build Coastguard Worker         payload_type,
1056*5a923131SAndroid Build Coastguard Worker         payload_size,
1057*5a923131SAndroid Build Coastguard Worker         num_bytes_downloaded,
1058*5a923131SAndroid Build Coastguard Worker         download_overhead_percentage,
1059*5a923131SAndroid Build Coastguard Worker         duration,
1060*5a923131SAndroid Build Coastguard Worker         duration_uptime,
1061*5a923131SAndroid Build Coastguard Worker         static_cast<int>(reboot_count),
1062*5a923131SAndroid Build Coastguard Worker         0);  // url_switch_count
1063*5a923131SAndroid Build Coastguard Worker   }
1064*5a923131SAndroid Build Coastguard Worker }
1065*5a923131SAndroid Build Coastguard Worker 
OTARebootSucceeded() const1066*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::OTARebootSucceeded() const {
1067*5a923131SAndroid Build Coastguard Worker   const auto current_slot = boot_control_->GetCurrentSlot();
1068*5a923131SAndroid Build Coastguard Worker   const string current_version = GetCurrentBuildVersion();
1069*5a923131SAndroid Build Coastguard Worker   int64_t previous_slot = -1;
1070*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsPreviousSlot, &previous_slot));
1071*5a923131SAndroid Build Coastguard Worker   string previous_version;
1072*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(
1073*5a923131SAndroid Build Coastguard Worker       prefs_->GetString(kPrefsPreviousVersion, &previous_version));
1074*5a923131SAndroid Build Coastguard Worker   if (previous_slot != current_slot) {
1075*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Detected a slot switch, OTA succeeded, device updated from "
1076*5a923131SAndroid Build Coastguard Worker               << previous_version << " to " << current_version
1077*5a923131SAndroid Build Coastguard Worker               << ", previous slot: " << previous_slot
1078*5a923131SAndroid Build Coastguard Worker               << " current slot: " << current_slot;
1079*5a923131SAndroid Build Coastguard Worker     if (previous_version == current_version) {
1080*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Previous version is the same as current version, this is "
1081*5a923131SAndroid Build Coastguard Worker                    "possibly a self-OTA.";
1082*5a923131SAndroid Build Coastguard Worker     }
1083*5a923131SAndroid Build Coastguard Worker     return true;
1084*5a923131SAndroid Build Coastguard Worker   } else {
1085*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Slot didn't switch, either the OTA is rolled back, or slot "
1086*5a923131SAndroid Build Coastguard Worker                  "switch never happened, or system not rebooted at all.";
1087*5a923131SAndroid Build Coastguard Worker     if (previous_version != current_version) {
1088*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Slot didn't change, but version changed from "
1089*5a923131SAndroid Build Coastguard Worker                 << previous_version << " to " << current_version
1090*5a923131SAndroid Build Coastguard Worker                 << " device could be flashed.";
1091*5a923131SAndroid Build Coastguard Worker     }
1092*5a923131SAndroid Build Coastguard Worker     return false;
1093*5a923131SAndroid Build Coastguard Worker   }
1094*5a923131SAndroid Build Coastguard Worker }
1095*5a923131SAndroid Build Coastguard Worker 
GetOTAUpdateResult() const1096*5a923131SAndroid Build Coastguard Worker OTAResult UpdateAttempterAndroid::GetOTAUpdateResult() const {
1097*5a923131SAndroid Build Coastguard Worker   // We only set |kPrefsSystemUpdatedMarker| if slot is actually switched, so
1098*5a923131SAndroid Build Coastguard Worker   // existence of this pref is sufficient indicator. Given that we have to
1099*5a923131SAndroid Build Coastguard Worker   // delete this pref after checking it. This is done in
1100*5a923131SAndroid Build Coastguard Worker   // |DeltaPerformer::ResetUpdateProgress| and
1101*5a923131SAndroid Build Coastguard Worker   // |UpdateAttempterAndroid::UpdateStateAfterReboot|
1102*5a923131SAndroid Build Coastguard Worker   auto slot_switch_attempted = prefs_->Exists(kPrefsUpdateCompletedOnBootId);
1103*5a923131SAndroid Build Coastguard Worker   auto system_rebooted = DidSystemReboot(prefs_);
1104*5a923131SAndroid Build Coastguard Worker   auto ota_successful = OTARebootSucceeded();
1105*5a923131SAndroid Build Coastguard Worker   if (ota_successful) {
1106*5a923131SAndroid Build Coastguard Worker     return OTAResult::OTA_SUCCESSFUL;
1107*5a923131SAndroid Build Coastguard Worker   }
1108*5a923131SAndroid Build Coastguard Worker   if (slot_switch_attempted) {
1109*5a923131SAndroid Build Coastguard Worker     if (system_rebooted) {
1110*5a923131SAndroid Build Coastguard Worker       // If we attempted slot switch, but still end up on the same slot, we
1111*5a923131SAndroid Build Coastguard Worker       // probably rolled back.
1112*5a923131SAndroid Build Coastguard Worker       return OTAResult::ROLLED_BACK;
1113*5a923131SAndroid Build Coastguard Worker     } else {
1114*5a923131SAndroid Build Coastguard Worker       return OTAResult::UPDATED_NEED_REBOOT;
1115*5a923131SAndroid Build Coastguard Worker     }
1116*5a923131SAndroid Build Coastguard Worker   }
1117*5a923131SAndroid Build Coastguard Worker   return OTAResult::NOT_ATTEMPTED;
1118*5a923131SAndroid Build Coastguard Worker }
1119*5a923131SAndroid Build Coastguard Worker 
UpdateStateAfterReboot(const OTAResult result)1120*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::UpdateStateAfterReboot(const OTAResult result) {
1121*5a923131SAndroid Build Coastguard Worker   const string current_version = GetCurrentBuildVersion();
1122*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN(!current_version.empty());
1123*5a923131SAndroid Build Coastguard Worker 
1124*5a923131SAndroid Build Coastguard Worker   // |UpdateStateAfterReboot()| is only called after system reboot, so record
1125*5a923131SAndroid Build Coastguard Worker   // boot id unconditionally
1126*5a923131SAndroid Build Coastguard Worker   string current_boot_id;
1127*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN(utils::GetBootId(&current_boot_id));
1128*5a923131SAndroid Build Coastguard Worker   prefs_->SetString(kPrefsBootId, current_boot_id);
1129*5a923131SAndroid Build Coastguard Worker   std::string slot_switch_indicator;
1130*5a923131SAndroid Build Coastguard Worker   prefs_->GetString(kPrefsUpdateCompletedOnBootId, &slot_switch_indicator);
1131*5a923131SAndroid Build Coastguard Worker   if (slot_switch_indicator != current_boot_id) {
1132*5a923131SAndroid Build Coastguard Worker     ClearUpdateCompletedMarker();
1133*5a923131SAndroid Build Coastguard Worker   }
1134*5a923131SAndroid Build Coastguard Worker 
1135*5a923131SAndroid Build Coastguard Worker   // If there's no record of previous version (e.g. due to a data wipe), we
1136*5a923131SAndroid Build Coastguard Worker   // save the info of current boot and skip the metrics report.
1137*5a923131SAndroid Build Coastguard Worker   if (!prefs_->Exists(kPrefsPreviousVersion)) {
1138*5a923131SAndroid Build Coastguard Worker     prefs_->SetString(kPrefsPreviousVersion, current_version);
1139*5a923131SAndroid Build Coastguard Worker     prefs_->SetInt64(kPrefsPreviousSlot, boot_control_->GetCurrentSlot());
1140*5a923131SAndroid Build Coastguard Worker     ClearMetricsPrefs();
1141*5a923131SAndroid Build Coastguard Worker     return;
1142*5a923131SAndroid Build Coastguard Worker   }
1143*5a923131SAndroid Build Coastguard Worker   // update_engine restarted under the same build and same slot.
1144*5a923131SAndroid Build Coastguard Worker   if (result != OTAResult::OTA_SUCCESSFUL) {
1145*5a923131SAndroid Build Coastguard Worker     // Increment the reboot number if |kPrefsNumReboots| exists. That pref is
1146*5a923131SAndroid Build Coastguard Worker     // set when we start a new update.
1147*5a923131SAndroid Build Coastguard Worker     if (prefs_->Exists(kPrefsNumReboots)) {
1148*5a923131SAndroid Build Coastguard Worker       int64_t reboot_count =
1149*5a923131SAndroid Build Coastguard Worker           metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
1150*5a923131SAndroid Build Coastguard Worker       metrics_utils::SetNumReboots(reboot_count + 1, prefs_);
1151*5a923131SAndroid Build Coastguard Worker     }
1152*5a923131SAndroid Build Coastguard Worker 
1153*5a923131SAndroid Build Coastguard Worker     if (result == OTAResult::ROLLED_BACK) {
1154*5a923131SAndroid Build Coastguard Worker       // This will release all space previously allocated for apex
1155*5a923131SAndroid Build Coastguard Worker       // decompression. If we detect a rollback, we should release space and
1156*5a923131SAndroid Build Coastguard Worker       // return the space to user. Any subsequent attempt to install OTA will
1157*5a923131SAndroid Build Coastguard Worker       // allocate space again anyway.
1158*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Detected a rollback, releasing space allocated for apex "
1159*5a923131SAndroid Build Coastguard Worker                    "deompression.";
1160*5a923131SAndroid Build Coastguard Worker       apex_handler_android_->AllocateSpace({});
1161*5a923131SAndroid Build Coastguard Worker       DeltaPerformer::ResetUpdateProgress(prefs_, false);
1162*5a923131SAndroid Build Coastguard Worker     }
1163*5a923131SAndroid Build Coastguard Worker     return;
1164*5a923131SAndroid Build Coastguard Worker   }
1165*5a923131SAndroid Build Coastguard Worker 
1166*5a923131SAndroid Build Coastguard Worker   // Now that the build version changes, report the update metrics.
1167*5a923131SAndroid Build Coastguard Worker   // TODO(xunchang) check the build version is larger than the previous one.
1168*5a923131SAndroid Build Coastguard Worker   prefs_->SetString(kPrefsPreviousVersion, current_version);
1169*5a923131SAndroid Build Coastguard Worker   prefs_->SetInt64(kPrefsPreviousSlot, boot_control_->GetCurrentSlot());
1170*5a923131SAndroid Build Coastguard Worker 
1171*5a923131SAndroid Build Coastguard Worker   bool previous_attempt_exists = prefs_->Exists(kPrefsPayloadAttemptNumber);
1172*5a923131SAndroid Build Coastguard Worker   // |kPrefsPayloadAttemptNumber| should be cleared upon successful update.
1173*5a923131SAndroid Build Coastguard Worker   if (previous_attempt_exists) {
1174*5a923131SAndroid Build Coastguard Worker     metrics_reporter_->ReportAbnormallyTerminatedUpdateAttemptMetrics();
1175*5a923131SAndroid Build Coastguard Worker   }
1176*5a923131SAndroid Build Coastguard Worker 
1177*5a923131SAndroid Build Coastguard Worker   metrics_utils::LoadAndReportTimeToReboot(
1178*5a923131SAndroid Build Coastguard Worker       metrics_reporter_.get(), prefs_, clock_.get());
1179*5a923131SAndroid Build Coastguard Worker   ClearMetricsPrefs();
1180*5a923131SAndroid Build Coastguard Worker 
1181*5a923131SAndroid Build Coastguard Worker   // Also reset the update progress if the build version has changed.
1182*5a923131SAndroid Build Coastguard Worker   if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
1183*5a923131SAndroid Build Coastguard Worker     LOG(WARNING) << "Unable to reset the update progress.";
1184*5a923131SAndroid Build Coastguard Worker   }
1185*5a923131SAndroid Build Coastguard Worker }
1186*5a923131SAndroid Build Coastguard Worker 
1187*5a923131SAndroid Build Coastguard Worker // Save the update start time. Reset the reboot count and attempt number if the
1188*5a923131SAndroid Build Coastguard Worker // update isn't a resume; otherwise increment the attempt number.
UpdatePrefsOnUpdateStart(bool is_resume)1189*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::UpdatePrefsOnUpdateStart(bool is_resume) {
1190*5a923131SAndroid Build Coastguard Worker   if (!is_resume) {
1191*5a923131SAndroid Build Coastguard Worker     metrics_utils::SetNumReboots(0, prefs_);
1192*5a923131SAndroid Build Coastguard Worker     metrics_utils::SetPayloadAttemptNumber(1, prefs_);
1193*5a923131SAndroid Build Coastguard Worker   } else {
1194*5a923131SAndroid Build Coastguard Worker     int64_t attempt_number =
1195*5a923131SAndroid Build Coastguard Worker         metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
1196*5a923131SAndroid Build Coastguard Worker     metrics_utils::SetPayloadAttemptNumber(attempt_number + 1, prefs_);
1197*5a923131SAndroid Build Coastguard Worker   }
1198*5a923131SAndroid Build Coastguard Worker   metrics_utils::SetUpdateTimestampStart(clock_->GetMonotonicTime(), prefs_);
1199*5a923131SAndroid Build Coastguard Worker   metrics_utils::SetUpdateBootTimestampStart(clock_->GetBootTime(), prefs_);
1200*5a923131SAndroid Build Coastguard Worker   ClearUpdateCompletedMarker();
1201*5a923131SAndroid Build Coastguard Worker }
1202*5a923131SAndroid Build Coastguard Worker 
ClearMetricsPrefs()1203*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ClearMetricsPrefs() {
1204*5a923131SAndroid Build Coastguard Worker   CHECK(prefs_);
1205*5a923131SAndroid Build Coastguard Worker   metric_bytes_downloaded_.Delete();
1206*5a923131SAndroid Build Coastguard Worker   prefs_->Delete(kPrefsNumReboots);
1207*5a923131SAndroid Build Coastguard Worker   prefs_->Delete(kPrefsSystemUpdatedMarker);
1208*5a923131SAndroid Build Coastguard Worker   prefs_->Delete(kPrefsUpdateTimestampStart);
1209*5a923131SAndroid Build Coastguard Worker   prefs_->Delete(kPrefsUpdateBootTimestampStart);
1210*5a923131SAndroid Build Coastguard Worker }
1211*5a923131SAndroid Build Coastguard Worker 
GetCurrentSlot() const1212*5a923131SAndroid Build Coastguard Worker BootControlInterface::Slot UpdateAttempterAndroid::GetCurrentSlot() const {
1213*5a923131SAndroid Build Coastguard Worker   return boot_control_->GetCurrentSlot();
1214*5a923131SAndroid Build Coastguard Worker }
1215*5a923131SAndroid Build Coastguard Worker 
GetTargetSlot() const1216*5a923131SAndroid Build Coastguard Worker BootControlInterface::Slot UpdateAttempterAndroid::GetTargetSlot() const {
1217*5a923131SAndroid Build Coastguard Worker   return GetCurrentSlot() == 0 ? 1 : 0;
1218*5a923131SAndroid Build Coastguard Worker }
1219*5a923131SAndroid Build Coastguard Worker 
AllocateSpaceForPayload(const std::string & metadata_filename,const vector<string> & key_value_pair_headers,Error * error)1220*5a923131SAndroid Build Coastguard Worker uint64_t UpdateAttempterAndroid::AllocateSpaceForPayload(
1221*5a923131SAndroid Build Coastguard Worker     const std::string& metadata_filename,
1222*5a923131SAndroid Build Coastguard Worker     const vector<string>& key_value_pair_headers,
1223*5a923131SAndroid Build Coastguard Worker     Error* error) {
1224*5a923131SAndroid Build Coastguard Worker   std::map<string, string> headers;
1225*5a923131SAndroid Build Coastguard Worker   if (!ParseKeyValuePairHeaders(key_value_pair_headers, &headers, error)) {
1226*5a923131SAndroid Build Coastguard Worker     return 0;
1227*5a923131SAndroid Build Coastguard Worker   }
1228*5a923131SAndroid Build Coastguard Worker   DeltaArchiveManifest manifest;
1229*5a923131SAndroid Build Coastguard Worker   brillo::Blob metadata_hash;
1230*5a923131SAndroid Build Coastguard Worker   if (!brillo::data_encoding::Base64Decode(
1231*5a923131SAndroid Build Coastguard Worker           headers[kPayloadPropertyMetadataHash], &metadata_hash)) {
1232*5a923131SAndroid Build Coastguard Worker     metadata_hash.clear();
1233*5a923131SAndroid Build Coastguard Worker   }
1234*5a923131SAndroid Build Coastguard Worker   if (!VerifyPayloadParseManifest(
1235*5a923131SAndroid Build Coastguard Worker           metadata_filename, ToStringView(metadata_hash), &manifest, error)) {
1236*5a923131SAndroid Build Coastguard Worker     return 0;
1237*5a923131SAndroid Build Coastguard Worker   }
1238*5a923131SAndroid Build Coastguard Worker 
1239*5a923131SAndroid Build Coastguard Worker   std::vector<ApexInfo> apex_infos(manifest.apex_info().begin(),
1240*5a923131SAndroid Build Coastguard Worker                                    manifest.apex_info().end());
1241*5a923131SAndroid Build Coastguard Worker   uint64_t apex_size_required = 0;
1242*5a923131SAndroid Build Coastguard Worker   if (apex_handler_android_ != nullptr) {
1243*5a923131SAndroid Build Coastguard Worker     auto result = apex_handler_android_->CalculateSize(apex_infos);
1244*5a923131SAndroid Build Coastguard Worker     if (!result.ok()) {
1245*5a923131SAndroid Build Coastguard Worker       LogAndSetGenericError(
1246*5a923131SAndroid Build Coastguard Worker           error,
1247*5a923131SAndroid Build Coastguard Worker           __LINE__,
1248*5a923131SAndroid Build Coastguard Worker           __FILE__,
1249*5a923131SAndroid Build Coastguard Worker           "Failed to calculate size required for compressed APEX");
1250*5a923131SAndroid Build Coastguard Worker       return 0;
1251*5a923131SAndroid Build Coastguard Worker     }
1252*5a923131SAndroid Build Coastguard Worker     apex_size_required = *result;
1253*5a923131SAndroid Build Coastguard Worker   }
1254*5a923131SAndroid Build Coastguard Worker 
1255*5a923131SAndroid Build Coastguard Worker   string payload_id = GetPayloadId(headers);
1256*5a923131SAndroid Build Coastguard Worker   uint64_t required_size = 0;
1257*5a923131SAndroid Build Coastguard Worker   ErrorCode error_code{};
1258*5a923131SAndroid Build Coastguard Worker 
1259*5a923131SAndroid Build Coastguard Worker   if (!DeltaPerformer::PreparePartitionsForUpdate(prefs_,
1260*5a923131SAndroid Build Coastguard Worker                                                   boot_control_,
1261*5a923131SAndroid Build Coastguard Worker                                                   GetTargetSlot(),
1262*5a923131SAndroid Build Coastguard Worker                                                   manifest,
1263*5a923131SAndroid Build Coastguard Worker                                                   payload_id,
1264*5a923131SAndroid Build Coastguard Worker                                                   &required_size,
1265*5a923131SAndroid Build Coastguard Worker                                                   &error_code)) {
1266*5a923131SAndroid Build Coastguard Worker     if (error_code == ErrorCode::kOverlayfsenabledError) {
1267*5a923131SAndroid Build Coastguard Worker       LogAndSetError(error,
1268*5a923131SAndroid Build Coastguard Worker                      __LINE__,
1269*5a923131SAndroid Build Coastguard Worker                      __FILE__,
1270*5a923131SAndroid Build Coastguard Worker                      "OverlayFS Shouldn't be enabled for OTA.",
1271*5a923131SAndroid Build Coastguard Worker                      error_code);
1272*5a923131SAndroid Build Coastguard Worker       return 0;
1273*5a923131SAndroid Build Coastguard Worker     }
1274*5a923131SAndroid Build Coastguard Worker     if (required_size == 0) {
1275*5a923131SAndroid Build Coastguard Worker       LogAndSetGenericError(
1276*5a923131SAndroid Build Coastguard Worker           error, __LINE__, __FILE__, "Failed to allocate space for payload.");
1277*5a923131SAndroid Build Coastguard Worker       return 0;
1278*5a923131SAndroid Build Coastguard Worker     } else {
1279*5a923131SAndroid Build Coastguard Worker       LOG(ERROR) << "Insufficient space for payload: " << required_size
1280*5a923131SAndroid Build Coastguard Worker                  << " bytes, apex decompression: " << apex_size_required
1281*5a923131SAndroid Build Coastguard Worker                  << " bytes";
1282*5a923131SAndroid Build Coastguard Worker       return required_size + apex_size_required;
1283*5a923131SAndroid Build Coastguard Worker     }
1284*5a923131SAndroid Build Coastguard Worker   }
1285*5a923131SAndroid Build Coastguard Worker 
1286*5a923131SAndroid Build Coastguard Worker   if (apex_size_required > 0 && apex_handler_android_ != nullptr &&
1287*5a923131SAndroid Build Coastguard Worker       !apex_handler_android_->AllocateSpace(apex_infos)) {
1288*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Insufficient space for apex decompression: "
1289*5a923131SAndroid Build Coastguard Worker                << apex_size_required << " bytes";
1290*5a923131SAndroid Build Coastguard Worker     return apex_size_required;
1291*5a923131SAndroid Build Coastguard Worker   }
1292*5a923131SAndroid Build Coastguard Worker 
1293*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Successfully allocated space for payload.";
1294*5a923131SAndroid Build Coastguard Worker   return 0;
1295*5a923131SAndroid Build Coastguard Worker }
1296*5a923131SAndroid Build Coastguard Worker 
CleanupSuccessfulUpdate(std::unique_ptr<CleanupSuccessfulUpdateCallbackInterface> callback,Error * error)1297*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::CleanupSuccessfulUpdate(
1298*5a923131SAndroid Build Coastguard Worker     std::unique_ptr<CleanupSuccessfulUpdateCallbackInterface> callback,
1299*5a923131SAndroid Build Coastguard Worker     Error* error) {
1300*5a923131SAndroid Build Coastguard Worker   if (cleanup_previous_update_code_.has_value()) {
1301*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "CleanupSuccessfulUpdate has previously completed with "
1302*5a923131SAndroid Build Coastguard Worker               << utils::ErrorCodeToString(*cleanup_previous_update_code_);
1303*5a923131SAndroid Build Coastguard Worker     if (callback) {
1304*5a923131SAndroid Build Coastguard Worker       callback->OnCleanupComplete(
1305*5a923131SAndroid Build Coastguard Worker           static_cast<int32_t>(*cleanup_previous_update_code_));
1306*5a923131SAndroid Build Coastguard Worker     }
1307*5a923131SAndroid Build Coastguard Worker     return;
1308*5a923131SAndroid Build Coastguard Worker   }
1309*5a923131SAndroid Build Coastguard Worker   if (callback) {
1310*5a923131SAndroid Build Coastguard Worker     auto callback_ptr = callback.get();
1311*5a923131SAndroid Build Coastguard Worker     cleanup_previous_update_callbacks_.emplace_back(std::move(callback));
1312*5a923131SAndroid Build Coastguard Worker     callback_ptr->RegisterForDeathNotifications([this, callback_ptr]() {
1313*5a923131SAndroid Build Coastguard Worker       RemoveCleanupPreviousUpdateCallback(callback_ptr);
1314*5a923131SAndroid Build Coastguard Worker     });
1315*5a923131SAndroid Build Coastguard Worker   }
1316*5a923131SAndroid Build Coastguard Worker   ScheduleCleanupPreviousUpdate();
1317*5a923131SAndroid Build Coastguard Worker }
1318*5a923131SAndroid Build Coastguard Worker 
setShouldSwitchSlotOnReboot(const std::string & metadata_filename,Error * error)1319*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::setShouldSwitchSlotOnReboot(
1320*5a923131SAndroid Build Coastguard Worker     const std::string& metadata_filename, Error* error) {
1321*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "setShouldSwitchSlotOnReboot(" << metadata_filename << ")";
1322*5a923131SAndroid Build Coastguard Worker   if (processor_->IsRunning()) {
1323*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
1324*5a923131SAndroid Build Coastguard Worker         error,
1325*5a923131SAndroid Build Coastguard Worker         __LINE__,
1326*5a923131SAndroid Build Coastguard Worker         __FILE__,
1327*5a923131SAndroid Build Coastguard Worker         "Already processing an update, cancel it first.");
1328*5a923131SAndroid Build Coastguard Worker   }
1329*5a923131SAndroid Build Coastguard Worker   DeltaArchiveManifest manifest;
1330*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(
1331*5a923131SAndroid Build Coastguard Worker       VerifyPayloadParseManifest(metadata_filename, &manifest, error));
1332*5a923131SAndroid Build Coastguard Worker 
1333*5a923131SAndroid Build Coastguard Worker   InstallPlan install_plan_;
1334*5a923131SAndroid Build Coastguard Worker   install_plan_.source_slot = GetCurrentSlot();
1335*5a923131SAndroid Build Coastguard Worker   install_plan_.target_slot = GetTargetSlot();
1336*5a923131SAndroid Build Coastguard Worker   // Don't do verity computation, just hash the partitions
1337*5a923131SAndroid Build Coastguard Worker   install_plan_.write_verity = false;
1338*5a923131SAndroid Build Coastguard Worker   // Don't run postinstall, we just need PostinstallAction to switch the slots.
1339*5a923131SAndroid Build Coastguard Worker   install_plan_.run_post_install = false;
1340*5a923131SAndroid Build Coastguard Worker   install_plan_.is_resume = true;
1341*5a923131SAndroid Build Coastguard Worker   // previous ApplyPayload() call may have requested powerwash, these
1342*5a923131SAndroid Build Coastguard Worker   // settings would be saved in `this->install_plan_`. Inherit that setting.
1343*5a923131SAndroid Build Coastguard Worker   install_plan_.powerwash_required = this->install_plan_.powerwash_required;
1344*5a923131SAndroid Build Coastguard Worker 
1345*5a923131SAndroid Build Coastguard Worker   CHECK_NE(install_plan_.source_slot, UINT32_MAX);
1346*5a923131SAndroid Build Coastguard Worker   CHECK_NE(install_plan_.target_slot, UINT32_MAX);
1347*5a923131SAndroid Build Coastguard Worker 
1348*5a923131SAndroid Build Coastguard Worker   auto postinstall_runner_action =
1349*5a923131SAndroid Build Coastguard Worker       std::make_unique<PostinstallRunnerAction>(boot_control_, hardware_);
1350*5a923131SAndroid Build Coastguard Worker   postinstall_runner_action->set_delegate(this);
1351*5a923131SAndroid Build Coastguard Worker 
1352*5a923131SAndroid Build Coastguard Worker   // If |kPrefsPostInstallSucceeded| is set, we know that we reached this
1353*5a923131SAndroid Build Coastguard Worker   // state by calling applyPayload() That applyPayload() call would have
1354*5a923131SAndroid Build Coastguard Worker   // already performed filesystem verification, therefore, we
1355*5a923131SAndroid Build Coastguard Worker   // can safely skip the verification to save time.
1356*5a923131SAndroid Build Coastguard Worker   bool postinstall_succeeded = false;
1357*5a923131SAndroid Build Coastguard Worker   if (prefs_->GetBoolean(kPrefsPostInstallSucceeded, &postinstall_succeeded) &&
1358*5a923131SAndroid Build Coastguard Worker       postinstall_succeeded) {
1359*5a923131SAndroid Build Coastguard Worker     auto install_plan_action =
1360*5a923131SAndroid Build Coastguard Worker         std::make_unique<InstallPlanAction>(install_plan_);
1361*5a923131SAndroid Build Coastguard Worker     BondActions(install_plan_action.get(), postinstall_runner_action.get());
1362*5a923131SAndroid Build Coastguard Worker     processor_->EnqueueAction(std::move(install_plan_action));
1363*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::FINALIZING);
1364*5a923131SAndroid Build Coastguard Worker   } else {
1365*5a923131SAndroid Build Coastguard Worker     ErrorCode error_code{};
1366*5a923131SAndroid Build Coastguard Worker     if (!boot_control_->GetDynamicPartitionControl()
1367*5a923131SAndroid Build Coastguard Worker              ->PreparePartitionsForUpdate(GetCurrentSlot(),
1368*5a923131SAndroid Build Coastguard Worker                                           GetTargetSlot(),
1369*5a923131SAndroid Build Coastguard Worker                                           manifest,
1370*5a923131SAndroid Build Coastguard Worker                                           false /* should update */,
1371*5a923131SAndroid Build Coastguard Worker                                           nullptr,
1372*5a923131SAndroid Build Coastguard Worker                                           &error_code)) {
1373*5a923131SAndroid Build Coastguard Worker       return LogAndSetGenericError(
1374*5a923131SAndroid Build Coastguard Worker           error, __LINE__, __FILE__, "Failed to PreparePartitionsForUpdate");
1375*5a923131SAndroid Build Coastguard Worker     }
1376*5a923131SAndroid Build Coastguard Worker     if (!install_plan_.ParsePartitions(manifest.partitions(),
1377*5a923131SAndroid Build Coastguard Worker                                        boot_control_,
1378*5a923131SAndroid Build Coastguard Worker                                        manifest.block_size(),
1379*5a923131SAndroid Build Coastguard Worker                                        &error_code)) {
1380*5a923131SAndroid Build Coastguard Worker       return LogAndSetError(error,
1381*5a923131SAndroid Build Coastguard Worker                             __LINE__,
1382*5a923131SAndroid Build Coastguard Worker                             __FILE__,
1383*5a923131SAndroid Build Coastguard Worker                             "Failed to LoadPartitionsFromSlots " +
1384*5a923131SAndroid Build Coastguard Worker                                 utils::ErrorCodeToString(error_code),
1385*5a923131SAndroid Build Coastguard Worker                             error_code);
1386*5a923131SAndroid Build Coastguard Worker     }
1387*5a923131SAndroid Build Coastguard Worker     auto install_plan_action =
1388*5a923131SAndroid Build Coastguard Worker         std::make_unique<InstallPlanAction>(install_plan_);
1389*5a923131SAndroid Build Coastguard Worker     auto filesystem_verifier_action =
1390*5a923131SAndroid Build Coastguard Worker         std::make_unique<FilesystemVerifierAction>(
1391*5a923131SAndroid Build Coastguard Worker             boot_control_->GetDynamicPartitionControl());
1392*5a923131SAndroid Build Coastguard Worker     filesystem_verifier_action->set_delegate(this);
1393*5a923131SAndroid Build Coastguard Worker     BondActions(install_plan_action.get(), filesystem_verifier_action.get());
1394*5a923131SAndroid Build Coastguard Worker     BondActions(filesystem_verifier_action.get(),
1395*5a923131SAndroid Build Coastguard Worker                 postinstall_runner_action.get());
1396*5a923131SAndroid Build Coastguard Worker     processor_->EnqueueAction(std::move(install_plan_action));
1397*5a923131SAndroid Build Coastguard Worker     processor_->EnqueueAction(std::move(filesystem_verifier_action));
1398*5a923131SAndroid Build Coastguard Worker     SetStatusAndNotify(UpdateStatus::VERIFYING);
1399*5a923131SAndroid Build Coastguard Worker   }
1400*5a923131SAndroid Build Coastguard Worker 
1401*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(postinstall_runner_action));
1402*5a923131SAndroid Build Coastguard Worker   ScheduleProcessingStart();
1403*5a923131SAndroid Build Coastguard Worker   return true;
1404*5a923131SAndroid Build Coastguard Worker }
1405*5a923131SAndroid Build Coastguard Worker 
resetShouldSwitchSlotOnReboot(Error * error)1406*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::resetShouldSwitchSlotOnReboot(Error* error) {
1407*5a923131SAndroid Build Coastguard Worker   if (processor_->IsRunning()) {
1408*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
1409*5a923131SAndroid Build Coastguard Worker         error,
1410*5a923131SAndroid Build Coastguard Worker         __LINE__,
1411*5a923131SAndroid Build Coastguard Worker         __FILE__,
1412*5a923131SAndroid Build Coastguard Worker         "Already processing an update, cancel it first.");
1413*5a923131SAndroid Build Coastguard Worker   }
1414*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(ClearUpdateCompletedMarker());
1415*5a923131SAndroid Build Coastguard Worker   // Update the boot flags so the current slot has higher priority.
1416*5a923131SAndroid Build Coastguard Worker   if (!boot_control_->SetActiveBootSlot(GetCurrentSlot())) {
1417*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
1418*5a923131SAndroid Build Coastguard Worker         error, __LINE__, __FILE__, "Failed to SetActiveBootSlot");
1419*5a923131SAndroid Build Coastguard Worker   }
1420*5a923131SAndroid Build Coastguard Worker 
1421*5a923131SAndroid Build Coastguard Worker   // Mark the current slot as successful again, since marking it as active
1422*5a923131SAndroid Build Coastguard Worker   // may reset the successful bit. We ignore the result of whether marking
1423*5a923131SAndroid Build Coastguard Worker   // the current slot as successful worked.
1424*5a923131SAndroid Build Coastguard Worker   if (!boot_control_->MarkBootSuccessfulAsync(Bind([](bool successful) {}))) {
1425*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
1426*5a923131SAndroid Build Coastguard Worker         error, __LINE__, __FILE__, "Failed to MarkBootSuccessfulAsync");
1427*5a923131SAndroid Build Coastguard Worker   }
1428*5a923131SAndroid Build Coastguard Worker 
1429*5a923131SAndroid Build Coastguard Worker   // Resets the warm reset property since we won't switch the slot.
1430*5a923131SAndroid Build Coastguard Worker   hardware_->SetWarmReset(false);
1431*5a923131SAndroid Build Coastguard Worker 
1432*5a923131SAndroid Build Coastguard Worker   // Resets the vbmeta digest.
1433*5a923131SAndroid Build Coastguard Worker   hardware_->SetVbmetaDigestForInactiveSlot(true /* reset */);
1434*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Slot switch cancelled.";
1435*5a923131SAndroid Build Coastguard Worker   SetStatusAndNotify(UpdateStatus::IDLE);
1436*5a923131SAndroid Build Coastguard Worker   return true;
1437*5a923131SAndroid Build Coastguard Worker }
1438*5a923131SAndroid Build Coastguard Worker 
ScheduleCleanupPreviousUpdate()1439*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::ScheduleCleanupPreviousUpdate() {
1440*5a923131SAndroid Build Coastguard Worker   // If a previous CleanupSuccessfulUpdate call has not finished, or an update
1441*5a923131SAndroid Build Coastguard Worker   // is in progress, skip enqueueing the action.
1442*5a923131SAndroid Build Coastguard Worker   if (processor_->IsRunning()) {
1443*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "Already processing an update. CleanupPreviousUpdate should "
1444*5a923131SAndroid Build Coastguard Worker               << "be done when the current update finishes.";
1445*5a923131SAndroid Build Coastguard Worker     return;
1446*5a923131SAndroid Build Coastguard Worker   }
1447*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Scheduling CleanupPreviousUpdateAction.";
1448*5a923131SAndroid Build Coastguard Worker   auto action =
1449*5a923131SAndroid Build Coastguard Worker       boot_control_->GetDynamicPartitionControl()
1450*5a923131SAndroid Build Coastguard Worker           ->GetCleanupPreviousUpdateAction(boot_control_, prefs_, this);
1451*5a923131SAndroid Build Coastguard Worker   processor_->EnqueueAction(std::move(action));
1452*5a923131SAndroid Build Coastguard Worker   processor_->set_delegate(this);
1453*5a923131SAndroid Build Coastguard Worker   SetStatusAndNotify(UpdateStatus::CLEANUP_PREVIOUS_UPDATE);
1454*5a923131SAndroid Build Coastguard Worker   processor_->StartProcessing();
1455*5a923131SAndroid Build Coastguard Worker }
1456*5a923131SAndroid Build Coastguard Worker 
TriggerPostinstall(const std::string & partition,Error * error)1457*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::TriggerPostinstall(const std::string& partition,
1458*5a923131SAndroid Build Coastguard Worker                                                 Error* error) {
1459*5a923131SAndroid Build Coastguard Worker   if (error) {
1460*5a923131SAndroid Build Coastguard Worker     return LogAndSetGenericError(
1461*5a923131SAndroid Build Coastguard Worker         error,
1462*5a923131SAndroid Build Coastguard Worker         __LINE__,
1463*5a923131SAndroid Build Coastguard Worker         __FILE__,
1464*5a923131SAndroid Build Coastguard Worker         __FUNCTION__ + std::string(" is not implemented"));
1465*5a923131SAndroid Build Coastguard Worker   }
1466*5a923131SAndroid Build Coastguard Worker   return false;
1467*5a923131SAndroid Build Coastguard Worker }
1468*5a923131SAndroid Build Coastguard Worker 
OnCleanupProgressUpdate(double progress)1469*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::OnCleanupProgressUpdate(double progress) {
1470*5a923131SAndroid Build Coastguard Worker   for (auto&& callback : cleanup_previous_update_callbacks_) {
1471*5a923131SAndroid Build Coastguard Worker     callback->OnCleanupProgressUpdate(progress);
1472*5a923131SAndroid Build Coastguard Worker   }
1473*5a923131SAndroid Build Coastguard Worker }
1474*5a923131SAndroid Build Coastguard Worker 
NotifyCleanupPreviousUpdateCallbacksAndClear()1475*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::NotifyCleanupPreviousUpdateCallbacksAndClear() {
1476*5a923131SAndroid Build Coastguard Worker   CHECK(cleanup_previous_update_code_.has_value());
1477*5a923131SAndroid Build Coastguard Worker   for (auto&& callback : cleanup_previous_update_callbacks_) {
1478*5a923131SAndroid Build Coastguard Worker     callback->OnCleanupComplete(
1479*5a923131SAndroid Build Coastguard Worker         static_cast<int32_t>(*cleanup_previous_update_code_));
1480*5a923131SAndroid Build Coastguard Worker   }
1481*5a923131SAndroid Build Coastguard Worker   cleanup_previous_update_callbacks_.clear();
1482*5a923131SAndroid Build Coastguard Worker }
1483*5a923131SAndroid Build Coastguard Worker 
RemoveCleanupPreviousUpdateCallback(CleanupSuccessfulUpdateCallbackInterface * callback)1484*5a923131SAndroid Build Coastguard Worker void UpdateAttempterAndroid::RemoveCleanupPreviousUpdateCallback(
1485*5a923131SAndroid Build Coastguard Worker     CleanupSuccessfulUpdateCallbackInterface* callback) {
1486*5a923131SAndroid Build Coastguard Worker   auto end_it =
1487*5a923131SAndroid Build Coastguard Worker       std::remove_if(cleanup_previous_update_callbacks_.begin(),
1488*5a923131SAndroid Build Coastguard Worker                      cleanup_previous_update_callbacks_.end(),
1489*5a923131SAndroid Build Coastguard Worker                      [&](const auto& e) { return e.get() == callback; });
1490*5a923131SAndroid Build Coastguard Worker   cleanup_previous_update_callbacks_.erase(
1491*5a923131SAndroid Build Coastguard Worker       end_it, cleanup_previous_update_callbacks_.end());
1492*5a923131SAndroid Build Coastguard Worker }
1493*5a923131SAndroid Build Coastguard Worker 
IsProductionBuild()1494*5a923131SAndroid Build Coastguard Worker bool UpdateAttempterAndroid::IsProductionBuild() {
1495*5a923131SAndroid Build Coastguard Worker   if (android::base::GetProperty("ro.build.type", "") != "userdebug" ||
1496*5a923131SAndroid Build Coastguard Worker       android::base::GetProperty("ro.build.tags", "") == "release-keys" ||
1497*5a923131SAndroid Build Coastguard Worker       android::base::GetProperty("ro.boot.verifiedbootstate", "") == "green") {
1498*5a923131SAndroid Build Coastguard Worker     return true;
1499*5a923131SAndroid Build Coastguard Worker   }
1500*5a923131SAndroid Build Coastguard Worker   return false;
1501*5a923131SAndroid Build Coastguard Worker }
1502*5a923131SAndroid Build Coastguard Worker 
1503*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
1504