blob: 82e3855f7a47f1ef4a1212b37276e992df23cb4f [file] [log] [blame]
Alex Deymo5e3ea272016-01-28 13:42:23 -08001//
2// Copyright (C) 2016 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/update_attempter_android.h"
18
19#include <algorithm>
Alex Deymo218397f2016-02-04 23:55:10 -080020#include <map>
Tianjie Xu90aaa102017-10-10 17:39:03 -070021#include <memory>
Alex Deymo5e3ea272016-01-28 13:42:23 -080022#include <utility>
23
Tianjie Xu90aaa102017-10-10 17:39:03 -070024#include <android-base/properties.h>
Alex Deymo5e3ea272016-01-28 13:42:23 -080025#include <base/bind.h>
26#include <base/logging.h>
Alex Deymo218397f2016-02-04 23:55:10 -080027#include <base/strings/string_number_conversions.h>
Alex Deymo5e3ea272016-01-28 13:42:23 -080028#include <brillo/bind_lambda.h>
Sen Jiang2703ef42017-03-16 13:36:21 -070029#include <brillo/data_encoding.h>
Alex Deymo5e3ea272016-01-28 13:42:23 -080030#include <brillo/message_loops/message_loop.h>
Alex Deymo218397f2016-02-04 23:55:10 -080031#include <brillo/strings/string_utils.h>
Sen Jiangacbdd1c2017-10-19 13:30:19 -070032#include <log/log_safetynet.h>
Alex Deymo5e3ea272016-01-28 13:42:23 -080033
34#include "update_engine/common/constants.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070035#include "update_engine/common/file_fetcher.h"
Alex Deymo5e3ea272016-01-28 13:42:23 -080036#include "update_engine/common/utils.h"
Alex Deymo03a4de72016-07-20 16:08:23 -070037#include "update_engine/daemon_state_interface.h"
Tianjie Xud4c5deb2017-10-24 11:17:03 -070038#include "update_engine/metrics_reporter_interface.h"
Tianjie Xu1b661142017-09-28 14:03:42 -070039#include "update_engine/metrics_utils.h"
Alex Deymo87792ea2016-07-25 15:40:36 -070040#include "update_engine/network_selector.h"
Alex Deymo5e3ea272016-01-28 13:42:23 -080041#include "update_engine/payload_consumer/download_action.h"
42#include "update_engine/payload_consumer/filesystem_verifier_action.h"
43#include "update_engine/payload_consumer/postinstall_runner_action.h"
Alex Deymo3b678db2016-02-09 11:50:06 -080044#include "update_engine/update_status_utils.h"
Alex Deymo5e3ea272016-01-28 13:42:23 -080045
Alex Deymo14c0da82016-07-20 16:45:45 -070046#ifndef _UE_SIDELOAD
47// Do not include support for external HTTP(s) urls when building
48// update_engine_sideload.
49#include "update_engine/libcurl_http_fetcher.h"
50#endif
51
Alex Deymo5e3ea272016-01-28 13:42:23 -080052using base::Bind;
Tianjie Xu90aaa102017-10-10 17:39:03 -070053using base::Time;
Alex Deymo5e3ea272016-01-28 13:42:23 -080054using base::TimeDelta;
55using base::TimeTicks;
56using std::shared_ptr;
57using std::string;
58using std::vector;
Aaron Wood7f92e2b2017-08-28 14:51:21 -070059using update_engine::UpdateEngineStatus;
Alex Deymo5e3ea272016-01-28 13:42:23 -080060
61namespace chromeos_update_engine {
62
63namespace {
64
Alex Deymo0d298542016-03-30 18:31:49 -070065// Minimum threshold to broadcast an status update in progress and time.
66const double kBroadcastThresholdProgress = 0.01; // 1%
67const int kBroadcastThresholdSeconds = 10;
68
Alex Deymo5e3ea272016-01-28 13:42:23 -080069const char* const kErrorDomain = "update_engine";
70// TODO(deymo): Convert the different errors to a numeric value to report them
71// back on the service error.
72const char* const kGenericError = "generic_error";
73
74// Log and set the error on the passed ErrorPtr.
75bool LogAndSetError(brillo::ErrorPtr* error,
76 const tracked_objects::Location& location,
77 const string& reason) {
78 brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason);
79 LOG(ERROR) << "Replying with failure: " << location.ToString() << ": "
80 << reason;
81 return false;
82}
83
Sen Jiangfe522822017-10-31 15:14:11 -070084bool GetHeaderAsBool(const string& header, bool default_value) {
85 int value = 0;
86 if (base::StringToInt(header, &value) && (value == 0 || value == 1))
87 return value == 1;
88 return default_value;
89}
90
Alex Deymo5e3ea272016-01-28 13:42:23 -080091} // namespace
92
93UpdateAttempterAndroid::UpdateAttempterAndroid(
Alex Deymo03a4de72016-07-20 16:08:23 -070094 DaemonStateInterface* daemon_state,
Alex Deymo5e3ea272016-01-28 13:42:23 -080095 PrefsInterface* prefs,
96 BootControlInterface* boot_control,
97 HardwareInterface* hardware)
98 : daemon_state_(daemon_state),
99 prefs_(prefs),
100 boot_control_(boot_control),
101 hardware_(hardware),
Tianjie Xu1b661142017-09-28 14:03:42 -0700102 processor_(new ActionProcessor()),
Tianjie Xud4c5deb2017-10-24 11:17:03 -0700103 clock_(new Clock()) {
104 metrics_reporter_ = metrics::CreateMetricsReporter();
Alex Deymo87792ea2016-07-25 15:40:36 -0700105 network_selector_ = network::CreateNetworkSelector();
Alex Deymo5e3ea272016-01-28 13:42:23 -0800106}
107
108UpdateAttempterAndroid::~UpdateAttempterAndroid() {
109 // Release ourselves as the ActionProcessor's delegate to prevent
110 // re-scheduling the updates due to the processing stopped.
111 processor_->set_delegate(nullptr);
112}
113
114void UpdateAttempterAndroid::Init() {
115 // In case of update_engine restart without a reboot we need to restore the
116 // reboot needed state.
Tianjie Xu90aaa102017-10-10 17:39:03 -0700117 if (UpdateCompletedOnThisBoot()) {
Alex Deymo0e061ae2016-02-09 17:49:03 -0800118 SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
Tianjie Xu90aaa102017-10-10 17:39:03 -0700119 } else {
Alex Deymo0e061ae2016-02-09 17:49:03 -0800120 SetStatusAndNotify(UpdateStatus::IDLE);
Tianjie Xu90aaa102017-10-10 17:39:03 -0700121 UpdatePrefsAndReportUpdateMetricsOnReboot();
122 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800123}
124
125bool UpdateAttempterAndroid::ApplyPayload(
126 const string& payload_url,
127 int64_t payload_offset,
128 int64_t payload_size,
129 const vector<string>& key_value_pair_headers,
130 brillo::ErrorPtr* error) {
131 if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
132 return LogAndSetError(
133 error, FROM_HERE, "An update already applied, waiting for reboot");
134 }
135 if (ongoing_update_) {
136 return LogAndSetError(
137 error, FROM_HERE, "Already processing an update, cancel it first.");
138 }
139 DCHECK(status_ == UpdateStatus::IDLE);
140
Alex Deymo218397f2016-02-04 23:55:10 -0800141 std::map<string, string> headers;
142 for (const string& key_value_pair : key_value_pair_headers) {
143 string key;
144 string value;
145 if (!brillo::string_utils::SplitAtFirst(
146 key_value_pair, "=", &key, &value, false)) {
147 return LogAndSetError(
148 error, FROM_HERE, "Passed invalid header: " + key_value_pair);
149 }
150 if (!headers.emplace(key, value).second)
151 return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key);
152 }
153
154 // Unique identifier for the payload. An empty string means that the payload
155 // can't be resumed.
156 string payload_id = (headers[kPayloadPropertyFileHash] +
157 headers[kPayloadPropertyMetadataHash]);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800158
159 // Setup the InstallPlan based on the request.
160 install_plan_ = InstallPlan();
161
162 install_plan_.download_url = payload_url;
163 install_plan_.version = "";
Alex Deymo0fd51ff2016-02-03 14:22:43 -0800164 base_offset_ = payload_offset;
Sen Jiang0affc2c2017-02-10 15:55:05 -0800165 InstallPlan::Payload payload;
166 payload.size = payload_size;
167 if (!payload.size) {
Alex Deymo218397f2016-02-04 23:55:10 -0800168 if (!base::StringToUint64(headers[kPayloadPropertyFileSize],
Sen Jiang0affc2c2017-02-10 15:55:05 -0800169 &payload.size)) {
170 payload.size = 0;
Alex Deymo218397f2016-02-04 23:55:10 -0800171 }
172 }
Sen Jiang2703ef42017-03-16 13:36:21 -0700173 if (!brillo::data_encoding::Base64Decode(headers[kPayloadPropertyFileHash],
Sen Jiang0affc2c2017-02-10 15:55:05 -0800174 &payload.hash)) {
Sen Jiang2703ef42017-03-16 13:36:21 -0700175 LOG(WARNING) << "Unable to decode base64 file hash: "
176 << headers[kPayloadPropertyFileHash];
177 }
Alex Deymo218397f2016-02-04 23:55:10 -0800178 if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize],
Sen Jiang0affc2c2017-02-10 15:55:05 -0800179 &payload.metadata_size)) {
180 payload.metadata_size = 0;
Alex Deymo218397f2016-02-04 23:55:10 -0800181 }
Sen Jiangcdd52062017-05-18 15:33:10 -0700182 // The |payload.type| is not used anymore since minor_version 3.
183 payload.type = InstallPayloadType::kUnknown;
Sen Jiang0affc2c2017-02-10 15:55:05 -0800184 install_plan_.payloads.push_back(payload);
185
Alex Deymo5e3ea272016-01-28 13:42:23 -0800186 // The |public_key_rsa| key would override the public key stored on disk.
187 install_plan_.public_key_rsa = "";
188
189 install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
190 install_plan_.is_resume = !payload_id.empty() &&
191 DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
192 if (!install_plan_.is_resume) {
193 if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
194 LOG(WARNING) << "Unable to reset the update progress.";
195 }
196 if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
197 LOG(WARNING) << "Unable to save the update check response hash.";
198 }
199 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800200 install_plan_.source_slot = boot_control_->GetCurrentSlot();
201 install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
Alex Deymofb905d92016-06-03 19:26:58 -0700202
Alex Deymofb905d92016-06-03 19:26:58 -0700203 install_plan_.powerwash_required =
Sen Jiangfe522822017-10-31 15:14:11 -0700204 GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false);
205
206 install_plan_.switch_slot_on_reboot =
207 GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true);
208
209 install_plan_.run_post_install = true;
210 // Optionally skip post install if and only if:
211 // a) we're resuming
212 // b) post install has already succeeded before
213 // c) RUN_POST_INSTALL is set to 0.
214 if (install_plan_.is_resume && prefs_->Exists(kPrefsPostInstallSucceeded)) {
215 bool post_install_succeeded = false;
216 prefs_->GetBoolean(kPrefsPostInstallSucceeded, &post_install_succeeded);
217 if (post_install_succeeded) {
218 install_plan_.run_post_install =
219 GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true);
220 }
221 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800222
Alex Deymo87792ea2016-07-25 15:40:36 -0700223 NetworkId network_id = kDefaultNetworkId;
224 if (!headers[kPayloadPropertyNetworkId].empty()) {
225 if (!base::StringToUint64(headers[kPayloadPropertyNetworkId],
226 &network_id)) {
227 return LogAndSetError(
228 error,
229 FROM_HERE,
230 "Invalid network_id: " + headers[kPayloadPropertyNetworkId]);
231 }
232 if (!network_selector_->SetProcessNetwork(network_id)) {
Sen Jiangcbd37c62017-09-12 15:04:35 -0700233 return LogAndSetError(
234 error,
235 FROM_HERE,
236 "Unable to set network_id: " + headers[kPayloadPropertyNetworkId]);
Alex Deymo87792ea2016-07-25 15:40:36 -0700237 }
238 }
239
Alex Deymo5e3ea272016-01-28 13:42:23 -0800240 LOG(INFO) << "Using this install plan:";
241 install_plan_.Dump();
242
Alex Deymo2c131bb2016-05-26 16:43:13 -0700243 BuildUpdateActions(payload_url);
Alex Deymofdd6dec2016-03-03 22:35:43 -0800244 // Setup extra headers.
245 HttpFetcher* fetcher = download_action_->http_fetcher();
246 if (!headers[kPayloadPropertyAuthorization].empty())
247 fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]);
248 if (!headers[kPayloadPropertyUserAgent].empty())
249 fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
250
Alex Deymo5e3ea272016-01-28 13:42:23 -0800251 SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
Alex Deymof2858572016-02-25 11:20:13 -0800252 ongoing_update_ = true;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800253
254 // Just in case we didn't update boot flags yet, make sure they're updated
255 // before any update processing starts. This will start the update process.
256 UpdateBootFlags();
Tianjie Xu90aaa102017-10-10 17:39:03 -0700257
258 UpdatePrefsOnUpdateStart(install_plan_.is_resume);
259 // TODO(xunchang) report the metrics for unresumable updates
260
Alex Deymo5e3ea272016-01-28 13:42:23 -0800261 return true;
262}
263
264bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) {
Alex Deymof2858572016-02-25 11:20:13 -0800265 if (!ongoing_update_)
266 return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend.");
267 processor_->SuspendProcessing();
268 return true;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800269}
270
271bool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) {
Alex Deymof2858572016-02-25 11:20:13 -0800272 if (!ongoing_update_)
273 return LogAndSetError(error, FROM_HERE, "No ongoing update to resume.");
274 processor_->ResumeProcessing();
275 return true;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800276}
277
278bool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) {
Alex Deymof2858572016-02-25 11:20:13 -0800279 if (!ongoing_update_)
Alex Deymo5e3ea272016-01-28 13:42:23 -0800280 return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel.");
Alex Deymof2858572016-02-25 11:20:13 -0800281 processor_->StopProcessing();
282 return true;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800283}
284
Alex Deymo3b678db2016-02-09 11:50:06 -0800285bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) {
286 LOG(INFO) << "Attempting to reset state from "
287 << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
288
289 switch (status_) {
290 case UpdateStatus::IDLE:
291 return true;
292
293 case UpdateStatus::UPDATED_NEED_REBOOT: {
294 // Remove the reboot marker so that if the machine is rebooted
295 // after resetting to idle state, it doesn't go back to
296 // UpdateStatus::UPDATED_NEED_REBOOT state.
297 bool ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId);
Tianjie Xu90aaa102017-10-10 17:39:03 -0700298 ClearMetricsPrefs();
Alex Deymo3b678db2016-02-09 11:50:06 -0800299
300 // Update the boot flags so the current slot has higher priority.
301 if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot()))
302 ret_value = false;
303
Alex Deymo52590332016-11-29 18:29:13 -0800304 // Mark the current slot as successful again, since marking it as active
305 // may reset the successful bit. We ignore the result of whether marking
306 // the current slot as successful worked.
307 if (!boot_control_->MarkBootSuccessfulAsync(Bind([](bool successful){})))
308 ret_value = false;
309
Alex Deymo3b678db2016-02-09 11:50:06 -0800310 if (!ret_value) {
311 return LogAndSetError(
312 error,
313 FROM_HERE,
314 "Failed to reset the status to ");
315 }
316
317 SetStatusAndNotify(UpdateStatus::IDLE);
318 LOG(INFO) << "Reset status successful";
319 return true;
320 }
321
322 default:
323 return LogAndSetError(
324 error,
325 FROM_HERE,
326 "Reset not allowed in this state. Cancel the ongoing update first");
327 }
328}
329
Alex Deymo5e3ea272016-01-28 13:42:23 -0800330void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
331 ErrorCode code) {
332 LOG(INFO) << "Processing Done.";
333
Alex Deymo5990bf32016-07-19 17:01:41 -0700334 switch (code) {
335 case ErrorCode::kSuccess:
336 // Update succeeded.
337 WriteUpdateCompletedMarker();
338 prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800339
Alex Deymo5990bf32016-07-19 17:01:41 -0700340 LOG(INFO) << "Update successfully applied, waiting to reboot.";
341 break;
342
343 case ErrorCode::kFilesystemCopierError:
344 case ErrorCode::kNewRootfsVerificationError:
345 case ErrorCode::kNewKernelVerificationError:
346 case ErrorCode::kFilesystemVerifierError:
347 case ErrorCode::kDownloadStateInitializationError:
348 // Reset the ongoing update for these errors so it starts from the
349 // beginning next time.
350 DeltaPerformer::ResetUpdateProgress(prefs_, false);
351 LOG(INFO) << "Resetting update progress.";
352 break;
353
Sen Jiangacbdd1c2017-10-19 13:30:19 -0700354 case ErrorCode::kPayloadTimestampError:
355 // SafetyNet logging, b/36232423
356 android_errorWriteLog(0x534e4554, "36232423");
357 break;
358
Alex Deymo5990bf32016-07-19 17:01:41 -0700359 default:
360 // Ignore all other error codes.
361 break;
Alex Deymo03a4de72016-07-20 16:08:23 -0700362 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800363
364 TerminateUpdateAndNotify(code);
365}
366
367void UpdateAttempterAndroid::ProcessingStopped(
368 const ActionProcessor* processor) {
369 TerminateUpdateAndNotify(ErrorCode::kUserCanceled);
370}
371
372void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor,
373 AbstractAction* action,
374 ErrorCode code) {
375 // Reset download progress regardless of whether or not the download
376 // action succeeded.
377 const string type = action->Type();
378 if (type == DownloadAction::StaticType()) {
Alex Deymo0d298542016-03-30 18:31:49 -0700379 download_progress_ = 0;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800380 }
Sen Jiangfe522822017-10-31 15:14:11 -0700381 if (type == PostinstallRunnerAction::StaticType()) {
382 bool succeeded =
383 code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive;
384 prefs_->SetBoolean(kPrefsPostInstallSucceeded, succeeded);
385 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800386 if (code != ErrorCode::kSuccess) {
387 // If an action failed, the ActionProcessor will cancel the whole thing.
388 return;
389 }
390 if (type == DownloadAction::StaticType()) {
391 SetStatusAndNotify(UpdateStatus::FINALIZING);
392 }
393}
394
395void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed,
396 uint64_t bytes_received,
397 uint64_t total) {
Alex Deymo0d298542016-03-30 18:31:49 -0700398 double progress = 0;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800399 if (total)
400 progress = static_cast<double>(bytes_received) / static_cast<double>(total);
Alex Deymo0d298542016-03-30 18:31:49 -0700401 if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total) {
Alex Deymo5e3ea272016-01-28 13:42:23 -0800402 download_progress_ = progress;
403 SetStatusAndNotify(UpdateStatus::DOWNLOADING);
Alex Deymo0d298542016-03-30 18:31:49 -0700404 } else {
405 ProgressUpdate(progress);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800406 }
Tianjie Xud4777a12017-10-24 14:54:18 -0700407
408 // Update the bytes downloaded in prefs.
409 int64_t current_bytes_downloaded =
410 metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
411 int64_t total_bytes_downloaded =
412 metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
413 prefs_->SetInt64(kPrefsCurrentBytesDownloaded,
414 current_bytes_downloaded + bytes_progressed);
415 prefs_->SetInt64(kPrefsTotalBytesDownloaded,
416 total_bytes_downloaded + bytes_progressed);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800417}
418
419bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
420 // TODO(deymo): Notify the DownloadAction that it should cancel the update
421 // download.
422 return false;
423}
424
425void UpdateAttempterAndroid::DownloadComplete() {
426 // Nothing needs to be done when the download completes.
427}
428
Alex Deymo0d298542016-03-30 18:31:49 -0700429void UpdateAttempterAndroid::ProgressUpdate(double progress) {
430 // Self throttle based on progress. Also send notifications if progress is
431 // too slow.
432 if (progress == 1.0 ||
433 progress - download_progress_ >= kBroadcastThresholdProgress ||
434 TimeTicks::Now() - last_notify_time_ >=
435 TimeDelta::FromSeconds(kBroadcastThresholdSeconds)) {
436 download_progress_ = progress;
437 SetStatusAndNotify(status_);
438 }
439}
440
Alex Deymo5e3ea272016-01-28 13:42:23 -0800441void UpdateAttempterAndroid::UpdateBootFlags() {
442 if (updated_boot_flags_) {
443 LOG(INFO) << "Already updated boot flags. Skipping.";
444 CompleteUpdateBootFlags(true);
445 return;
446 }
447 // This is purely best effort.
448 LOG(INFO) << "Marking booted slot as good.";
449 if (!boot_control_->MarkBootSuccessfulAsync(
450 Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags,
451 base::Unretained(this)))) {
452 LOG(ERROR) << "Failed to mark current boot as successful.";
453 CompleteUpdateBootFlags(false);
454 }
455}
456
457void UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) {
458 updated_boot_flags_ = true;
459 ScheduleProcessingStart();
460}
461
462void UpdateAttempterAndroid::ScheduleProcessingStart() {
463 LOG(INFO) << "Scheduling an action processor start.";
464 brillo::MessageLoop::current()->PostTask(
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700465 FROM_HERE,
466 Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
467 base::Unretained(processor_.get())));
Alex Deymo5e3ea272016-01-28 13:42:23 -0800468}
469
470void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
471 if (status_ == UpdateStatus::IDLE) {
472 LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called.";
473 return;
474 }
475
Alex Deymo0d298542016-03-30 18:31:49 -0700476 download_progress_ = 0;
Alex Deymo5e3ea272016-01-28 13:42:23 -0800477 actions_.clear();
478 UpdateStatus new_status =
479 (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
480 : UpdateStatus::IDLE);
481 SetStatusAndNotify(new_status);
482 ongoing_update_ = false;
483
484 for (auto observer : daemon_state_->service_observers())
485 observer->SendPayloadApplicationComplete(error_code);
Tianjie Xu1b661142017-09-28 14:03:42 -0700486
Tianjie Xu90aaa102017-10-10 17:39:03 -0700487 CollectAndReportUpdateMetricsOnUpdateFinished(error_code);
488 ClearMetricsPrefs();
489 if (error_code == ErrorCode::kSuccess) {
490 metrics_utils::SetSystemUpdatedMarker(clock_.get(), prefs_);
Tianjie Xud4777a12017-10-24 14:54:18 -0700491 // Clear the total bytes downloaded if and only if the update succeeds.
492 prefs_->SetInt64(kPrefsTotalBytesDownloaded, 0);
Tianjie Xu90aaa102017-10-10 17:39:03 -0700493 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800494}
495
496void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
497 status_ = status;
Sen Jiang2d1c87b2017-07-14 10:46:14 -0700498 size_t payload_size =
499 install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size;
Aaron Wood7f92e2b2017-08-28 14:51:21 -0700500 UpdateEngineStatus status_to_send = {.status = status_,
501 .progress = download_progress_,
502 .new_size_bytes = payload_size};
503
Alex Deymo5e3ea272016-01-28 13:42:23 -0800504 for (auto observer : daemon_state_->service_observers()) {
Aaron Wood7f92e2b2017-08-28 14:51:21 -0700505 observer->SendStatusUpdate(status_to_send);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800506 }
507 last_notify_time_ = TimeTicks::Now();
508}
509
Alex Deymo2c131bb2016-05-26 16:43:13 -0700510void UpdateAttempterAndroid::BuildUpdateActions(const string& url) {
Alex Deymo5e3ea272016-01-28 13:42:23 -0800511 CHECK(!processor_->IsRunning());
512 processor_->set_delegate(this);
513
514 // Actions:
515 shared_ptr<InstallPlanAction> install_plan_action(
516 new InstallPlanAction(install_plan_));
517
Alex Deymo2c131bb2016-05-26 16:43:13 -0700518 HttpFetcher* download_fetcher = nullptr;
519 if (FileFetcher::SupportedUrl(url)) {
520 DLOG(INFO) << "Using FileFetcher for file URL.";
521 download_fetcher = new FileFetcher();
522 } else {
Alex Deymo14c0da82016-07-20 16:45:45 -0700523#ifdef _UE_SIDELOAD
524 LOG(FATAL) << "Unsupported sideload URI: " << url;
525#else
Alex Deymo2c131bb2016-05-26 16:43:13 -0700526 LibcurlHttpFetcher* libcurl_fetcher =
527 new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
528 libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
529 download_fetcher = libcurl_fetcher;
Alex Deymo14c0da82016-07-20 16:45:45 -0700530#endif // _UE_SIDELOAD
Alex Deymo2c131bb2016-05-26 16:43:13 -0700531 }
Sen Jiang5ae865b2017-04-18 14:24:40 -0700532 shared_ptr<DownloadAction> download_action(
533 new DownloadAction(prefs_,
534 boot_control_,
535 hardware_,
536 nullptr, // system_state, not used.
537 download_fetcher)); // passes ownership
Sen Jiangfef85fd2016-03-25 15:32:49 -0700538 shared_ptr<FilesystemVerifierAction> filesystem_verifier_action(
Sen Jiange6e4bb92016-04-05 14:59:12 -0700539 new FilesystemVerifierAction());
Alex Deymo5e3ea272016-01-28 13:42:23 -0800540
541 shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
Alex Deymofb905d92016-06-03 19:26:58 -0700542 new PostinstallRunnerAction(boot_control_, hardware_));
Alex Deymo5e3ea272016-01-28 13:42:23 -0800543
544 download_action->set_delegate(this);
Sen Jiang5ae865b2017-04-18 14:24:40 -0700545 download_action->set_base_offset(base_offset_);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800546 download_action_ = download_action;
Alex Deymob6eef732016-06-10 12:58:11 -0700547 postinstall_runner_action->set_delegate(this);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800548
549 actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
550 actions_.push_back(shared_ptr<AbstractAction>(download_action));
Sen Jiangfef85fd2016-03-25 15:32:49 -0700551 actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action));
Alex Deymo5e3ea272016-01-28 13:42:23 -0800552 actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
553
554 // Bond them together. We have to use the leaf-types when calling
555 // BondActions().
556 BondActions(install_plan_action.get(), download_action.get());
Sen Jiangfef85fd2016-03-25 15:32:49 -0700557 BondActions(download_action.get(), filesystem_verifier_action.get());
558 BondActions(filesystem_verifier_action.get(),
Alex Deymo5e3ea272016-01-28 13:42:23 -0800559 postinstall_runner_action.get());
560
561 // Enqueue the actions.
562 for (const shared_ptr<AbstractAction>& action : actions_)
563 processor_->EnqueueAction(action.get());
564}
565
Alex Deymo5e3ea272016-01-28 13:42:23 -0800566bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
567 string boot_id;
568 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
569 prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id);
570 return true;
571}
572
573bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() {
574 // In case of an update_engine restart without a reboot, we stored the boot_id
575 // when the update was completed by setting a pref, so we can check whether
576 // the last update was on this boot or a previous one.
577 string boot_id;
578 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
579
580 string update_completed_on_boot_id;
581 return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
582 prefs_->GetString(kPrefsUpdateCompletedOnBootId,
583 &update_completed_on_boot_id) &&
584 update_completed_on_boot_id == boot_id);
585}
586
Tianjie Xu90aaa102017-10-10 17:39:03 -0700587// Collect and report the android metrics when we terminate the update.
588void UpdateAttempterAndroid::CollectAndReportUpdateMetricsOnUpdateFinished(
589 ErrorCode error_code) {
590 int64_t attempt_number =
591 metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
592 PayloadType payload_type = kPayloadTypeFull;
593 int64_t payload_size = 0;
594 for (const auto& p : install_plan_.payloads) {
595 if (p.type == InstallPayloadType::kDelta)
596 payload_type = kPayloadTypeDelta;
597 payload_size += p.size;
598 }
599
600 metrics::AttemptResult attempt_result =
601 metrics_utils::GetAttemptResult(error_code);
602 Time attempt_start_time = Time::FromInternalValue(
603 metrics_utils::GetPersistedValue(kPrefsUpdateTimestampStart, prefs_));
Tianjie Xu52c678c2017-10-18 15:52:27 -0700604 TimeDelta duration = clock_->GetBootTime() - attempt_start_time;
Tianjie Xu90aaa102017-10-10 17:39:03 -0700605 TimeDelta duration_uptime = clock_->GetMonotonicTime() - attempt_start_time;
606
607 metrics_reporter_->ReportUpdateAttemptMetrics(
608 nullptr, // system_state
609 static_cast<int>(attempt_number),
610 payload_type,
Tianjie Xu52c678c2017-10-18 15:52:27 -0700611 duration,
Tianjie Xu90aaa102017-10-10 17:39:03 -0700612 duration_uptime,
613 payload_size,
614 attempt_result,
615 error_code);
616
Tianjie Xud4777a12017-10-24 14:54:18 -0700617 int64_t current_bytes_downloaded =
618 metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, prefs_);
619 metrics_reporter_->ReportUpdateAttemptDownloadMetrics(
620 current_bytes_downloaded,
621 0,
622 DownloadSource::kNumDownloadSources,
623 metrics::DownloadErrorCode::kUnset,
624 metrics::ConnectionType::kUnset);
625
Tianjie Xu90aaa102017-10-10 17:39:03 -0700626 if (error_code == ErrorCode::kSuccess) {
627 int64_t reboot_count =
628 metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
629 string build_version;
630 prefs_->GetString(kPrefsPreviousVersion, &build_version);
Tianjie Xud4777a12017-10-24 14:54:18 -0700631
632 // For android metrics, we only care about the total bytes downloaded
633 // for all sources; for now we assume the only download source is
634 // HttpsServer.
635 int64_t total_bytes_downloaded =
636 metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, prefs_);
637 int64_t num_bytes_downloaded[kNumDownloadSources] = {};
638 num_bytes_downloaded[DownloadSource::kDownloadSourceHttpsServer] =
639 total_bytes_downloaded;
640
641 int download_overhead_percentage = 0;
642 if (current_bytes_downloaded > 0) {
643 download_overhead_percentage =
644 (total_bytes_downloaded - current_bytes_downloaded) * 100ull /
645 current_bytes_downloaded;
646 }
Tianjie Xu90aaa102017-10-10 17:39:03 -0700647 metrics_reporter_->ReportSuccessfulUpdateMetrics(
648 static_cast<int>(attempt_number),
649 0, // update abandoned count
650 payload_type,
651 payload_size,
Tianjie Xud4777a12017-10-24 14:54:18 -0700652 num_bytes_downloaded,
653 download_overhead_percentage,
Tianjie Xu52c678c2017-10-18 15:52:27 -0700654 duration,
Tianjie Xu90aaa102017-10-10 17:39:03 -0700655 static_cast<int>(reboot_count),
656 0); // url_switch_count
657 }
658}
659
660void UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() {
661 string current_boot_id;
662 TEST_AND_RETURN(utils::GetBootId(&current_boot_id));
663 // Example: [ro.build.version.incremental]: [4292972]
664 string current_version =
665 android::base::GetProperty("ro.build.version.incremental", "");
666 TEST_AND_RETURN(!current_version.empty());
667
668 // If there's no record of previous version (e.g. due to a data wipe), we
669 // save the info of current boot and skip the metrics report.
670 if (!prefs_->Exists(kPrefsPreviousVersion)) {
671 prefs_->SetString(kPrefsBootId, current_boot_id);
672 prefs_->SetString(kPrefsPreviousVersion, current_version);
673 ClearMetricsPrefs();
674 return;
675 }
676 string previous_version;
677 // update_engine restarted under the same build.
678 // TODO(xunchang) identify and report rollback by checking UpdateMarker.
679 if (prefs_->GetString(kPrefsPreviousVersion, &previous_version) &&
680 previous_version == current_version) {
681 string last_boot_id;
682 bool is_reboot = prefs_->Exists(kPrefsBootId) &&
683 (prefs_->GetString(kPrefsBootId, &last_boot_id) &&
684 last_boot_id != current_boot_id);
685 // Increment the reboot number if |kPrefsNumReboots| exists. That pref is
686 // set when we start a new update.
687 if (is_reboot && prefs_->Exists(kPrefsNumReboots)) {
688 prefs_->SetString(kPrefsBootId, current_boot_id);
689 int64_t reboot_count =
690 metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
691 metrics_utils::SetNumReboots(reboot_count + 1, prefs_);
692 }
693 return;
694 }
695
696 // Now that the build version changes, report the update metrics.
697 // TODO(xunchang) check the build version is larger than the previous one.
698 prefs_->SetString(kPrefsBootId, current_boot_id);
699 prefs_->SetString(kPrefsPreviousVersion, current_version);
700
701 bool previous_attempt_exists = prefs_->Exists(kPrefsPayloadAttemptNumber);
702 // |kPrefsPayloadAttemptNumber| should be cleared upon successful update.
703 if (previous_attempt_exists) {
704 metrics_reporter_->ReportAbnormallyTerminatedUpdateAttemptMetrics();
705 }
706
707 metrics_utils::LoadAndReportTimeToReboot(
708 metrics_reporter_.get(), prefs_, clock_.get());
709 ClearMetricsPrefs();
710}
711
712// Save the update start time. Reset the reboot count and attempt number if the
713// update isn't a resume; otherwise increment the attempt number.
714void UpdateAttempterAndroid::UpdatePrefsOnUpdateStart(bool is_resume) {
715 if (!is_resume) {
716 metrics_utils::SetNumReboots(0, prefs_);
717 metrics_utils::SetPayloadAttemptNumber(1, prefs_);
718 } else {
719 int64_t attempt_number =
720 metrics_utils::GetPersistedValue(kPrefsPayloadAttemptNumber, prefs_);
721 metrics_utils::SetPayloadAttemptNumber(attempt_number + 1, prefs_);
722 }
723 Time update_start_time = clock_->GetMonotonicTime();
724 metrics_utils::SetUpdateTimestampStart(update_start_time, prefs_);
725}
726
727void UpdateAttempterAndroid::ClearMetricsPrefs() {
728 CHECK(prefs_);
Tianjie Xud4777a12017-10-24 14:54:18 -0700729 prefs_->Delete(kPrefsCurrentBytesDownloaded);
Tianjie Xu90aaa102017-10-10 17:39:03 -0700730 prefs_->Delete(kPrefsNumReboots);
731 prefs_->Delete(kPrefsPayloadAttemptNumber);
732 prefs_->Delete(kPrefsSystemUpdatedMarker);
733 prefs_->Delete(kPrefsUpdateTimestampStart);
734}
735
Alex Deymo5e3ea272016-01-28 13:42:23 -0800736} // namespace chromeos_update_engine