blob: 90501fb5b452a20a51f6034b70abd5bbf3e26050 [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>
Alex Deymo5e3ea272016-01-28 13:42:23 -080021#include <utility>
22
23#include <base/bind.h>
24#include <base/logging.h>
Alex Deymo218397f2016-02-04 23:55:10 -080025#include <base/strings/string_number_conversions.h>
Alex Deymo5e3ea272016-01-28 13:42:23 -080026#include <brillo/bind_lambda.h>
27#include <brillo/message_loops/message_loop.h>
Alex Deymo218397f2016-02-04 23:55:10 -080028#include <brillo/strings/string_utils.h>
Alex Deymo5e3ea272016-01-28 13:42:23 -080029
30#include "update_engine/common/constants.h"
31#include "update_engine/common/libcurl_http_fetcher.h"
32#include "update_engine/common/multi_range_http_fetcher.h"
33#include "update_engine/common/utils.h"
34#include "update_engine/daemon_state_android.h"
35#include "update_engine/payload_consumer/download_action.h"
36#include "update_engine/payload_consumer/filesystem_verifier_action.h"
37#include "update_engine/payload_consumer/postinstall_runner_action.h"
Alex Deymo3b678db2016-02-09 11:50:06 -080038#include "update_engine/update_status_utils.h"
Alex Deymo5e3ea272016-01-28 13:42:23 -080039
40using base::Bind;
41using base::TimeDelta;
42using base::TimeTicks;
43using std::shared_ptr;
44using std::string;
45using std::vector;
46
47namespace chromeos_update_engine {
48
49namespace {
50
51const char* const kErrorDomain = "update_engine";
52// TODO(deymo): Convert the different errors to a numeric value to report them
53// back on the service error.
54const char* const kGenericError = "generic_error";
55
56// Log and set the error on the passed ErrorPtr.
57bool LogAndSetError(brillo::ErrorPtr* error,
58 const tracked_objects::Location& location,
59 const string& reason) {
60 brillo::Error::AddTo(error, location, kErrorDomain, kGenericError, reason);
61 LOG(ERROR) << "Replying with failure: " << location.ToString() << ": "
62 << reason;
63 return false;
64}
65
66} // namespace
67
68UpdateAttempterAndroid::UpdateAttempterAndroid(
69 DaemonStateAndroid* daemon_state,
70 PrefsInterface* prefs,
71 BootControlInterface* boot_control,
72 HardwareInterface* hardware)
73 : daemon_state_(daemon_state),
74 prefs_(prefs),
75 boot_control_(boot_control),
76 hardware_(hardware),
77 processor_(new ActionProcessor()) {
78}
79
80UpdateAttempterAndroid::~UpdateAttempterAndroid() {
81 // Release ourselves as the ActionProcessor's delegate to prevent
82 // re-scheduling the updates due to the processing stopped.
83 processor_->set_delegate(nullptr);
84}
85
86void UpdateAttempterAndroid::Init() {
87 // In case of update_engine restart without a reboot we need to restore the
88 // reboot needed state.
89 if (UpdateCompletedOnThisBoot())
Alex Deymo0e061ae2016-02-09 17:49:03 -080090 SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
Alex Deymo5e3ea272016-01-28 13:42:23 -080091 else
Alex Deymo0e061ae2016-02-09 17:49:03 -080092 SetStatusAndNotify(UpdateStatus::IDLE);
Alex Deymo5e3ea272016-01-28 13:42:23 -080093}
94
95bool UpdateAttempterAndroid::ApplyPayload(
96 const string& payload_url,
97 int64_t payload_offset,
98 int64_t payload_size,
99 const vector<string>& key_value_pair_headers,
100 brillo::ErrorPtr* error) {
101 if (status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
102 return LogAndSetError(
103 error, FROM_HERE, "An update already applied, waiting for reboot");
104 }
105 if (ongoing_update_) {
106 return LogAndSetError(
107 error, FROM_HERE, "Already processing an update, cancel it first.");
108 }
109 DCHECK(status_ == UpdateStatus::IDLE);
110
Alex Deymo218397f2016-02-04 23:55:10 -0800111 std::map<string, string> headers;
112 for (const string& key_value_pair : key_value_pair_headers) {
113 string key;
114 string value;
115 if (!brillo::string_utils::SplitAtFirst(
116 key_value_pair, "=", &key, &value, false)) {
117 return LogAndSetError(
118 error, FROM_HERE, "Passed invalid header: " + key_value_pair);
119 }
120 if (!headers.emplace(key, value).second)
121 return LogAndSetError(error, FROM_HERE, "Passed repeated key: " + key);
122 }
123
124 // Unique identifier for the payload. An empty string means that the payload
125 // can't be resumed.
126 string payload_id = (headers[kPayloadPropertyFileHash] +
127 headers[kPayloadPropertyMetadataHash]);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800128
129 // Setup the InstallPlan based on the request.
130 install_plan_ = InstallPlan();
131
132 install_plan_.download_url = payload_url;
133 install_plan_.version = "";
Alex Deymo0fd51ff2016-02-03 14:22:43 -0800134 base_offset_ = payload_offset;
Alex Deymo218397f2016-02-04 23:55:10 -0800135 install_plan_.payload_size = payload_size;
136 if (!install_plan_.payload_size) {
137 if (!base::StringToUint64(headers[kPayloadPropertyFileSize],
138 &install_plan_.payload_size)) {
139 install_plan_.payload_size = 0;
140 }
141 }
142 install_plan_.payload_hash = headers[kPayloadPropertyFileHash];
143 if (!base::StringToUint64(headers[kPayloadPropertyMetadataSize],
144 &install_plan_.metadata_size)) {
145 install_plan_.metadata_size = 0;
146 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800147 install_plan_.metadata_signature = "";
148 // The |public_key_rsa| key would override the public key stored on disk.
149 install_plan_.public_key_rsa = "";
150
151 install_plan_.hash_checks_mandatory = hardware_->IsOfficialBuild();
152 install_plan_.is_resume = !payload_id.empty() &&
153 DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
154 if (!install_plan_.is_resume) {
155 if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
156 LOG(WARNING) << "Unable to reset the update progress.";
157 }
158 if (!prefs_->SetString(kPrefsUpdateCheckResponseHash, payload_id)) {
159 LOG(WARNING) << "Unable to save the update check response hash.";
160 }
161 }
162 // The |is_full_update| is not used anymore since minor_version 3.
163 install_plan_.is_full_update = true;
164
165 install_plan_.source_slot = boot_control_->GetCurrentSlot();
166 install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
167 install_plan_.powerwash_required = false;
168
169 LOG(INFO) << "Using this install plan:";
170 install_plan_.Dump();
171
172 BuildUpdateActions();
173 SetupDownload();
174 cpu_limiter_.StartLimiter();
175 SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
176
177 // Just in case we didn't update boot flags yet, make sure they're updated
178 // before any update processing starts. This will start the update process.
179 UpdateBootFlags();
180 return true;
181}
182
183bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) {
184 // TODO(deymo): Implement suspend/resume.
185 return LogAndSetError(error, FROM_HERE, "Suspend/resume not implemented");
186}
187
188bool UpdateAttempterAndroid::ResumeUpdate(brillo::ErrorPtr* error) {
189 // TODO(deymo): Implement suspend/resume.
190 return LogAndSetError(error, FROM_HERE, "Suspend/resume not implemented");
191}
192
193bool UpdateAttempterAndroid::CancelUpdate(brillo::ErrorPtr* error) {
194 if (status_ == UpdateStatus::IDLE ||
195 status_ == UpdateStatus::UPDATED_NEED_REBOOT) {
196 return LogAndSetError(error, FROM_HERE, "No ongoing update to cancel.");
197 }
198
199 // TODO(deymo): Implement cancel.
200 return LogAndSetError(error, FROM_HERE, "Cancel not implemented");
201}
202
Alex Deymo3b678db2016-02-09 11:50:06 -0800203bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) {
204 LOG(INFO) << "Attempting to reset state from "
205 << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
206
207 switch (status_) {
208 case UpdateStatus::IDLE:
209 return true;
210
211 case UpdateStatus::UPDATED_NEED_REBOOT: {
212 // Remove the reboot marker so that if the machine is rebooted
213 // after resetting to idle state, it doesn't go back to
214 // UpdateStatus::UPDATED_NEED_REBOOT state.
215 bool ret_value = prefs_->Delete(kPrefsUpdateCompletedOnBootId);
216
217 // Update the boot flags so the current slot has higher priority.
218 if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot()))
219 ret_value = false;
220
221 if (!ret_value) {
222 return LogAndSetError(
223 error,
224 FROM_HERE,
225 "Failed to reset the status to ");
226 }
227
228 SetStatusAndNotify(UpdateStatus::IDLE);
229 LOG(INFO) << "Reset status successful";
230 return true;
231 }
232
233 default:
234 return LogAndSetError(
235 error,
236 FROM_HERE,
237 "Reset not allowed in this state. Cancel the ongoing update first");
238 }
239}
240
Alex Deymo5e3ea272016-01-28 13:42:23 -0800241void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor,
242 ErrorCode code) {
243 LOG(INFO) << "Processing Done.";
244
245 if (code == ErrorCode::kSuccess) {
246 // Update succeeded.
247 WriteUpdateCompletedMarker();
248 prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
249 DeltaPerformer::ResetUpdateProgress(prefs_, false);
250
251 LOG(INFO) << "Update successfully applied, waiting to reboot.";
252 }
253
254 TerminateUpdateAndNotify(code);
255}
256
257void UpdateAttempterAndroid::ProcessingStopped(
258 const ActionProcessor* processor) {
259 TerminateUpdateAndNotify(ErrorCode::kUserCanceled);
260}
261
262void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor,
263 AbstractAction* action,
264 ErrorCode code) {
265 // Reset download progress regardless of whether or not the download
266 // action succeeded.
267 const string type = action->Type();
268 if (type == DownloadAction::StaticType()) {
269 download_progress_ = 0.0;
270 }
271 if (code != ErrorCode::kSuccess) {
272 // If an action failed, the ActionProcessor will cancel the whole thing.
273 return;
274 }
275 if (type == DownloadAction::StaticType()) {
276 SetStatusAndNotify(UpdateStatus::FINALIZING);
277 }
278}
279
280void UpdateAttempterAndroid::BytesReceived(uint64_t bytes_progressed,
281 uint64_t bytes_received,
282 uint64_t total) {
283 double progress = 0.;
284 if (total)
285 progress = static_cast<double>(bytes_received) / static_cast<double>(total);
286 // Self throttle based on progress. Also send notifications if
287 // progress is too slow.
288 const double kDeltaPercent = 0.01; // 1%
289 if (status_ != UpdateStatus::DOWNLOADING || bytes_received == total ||
290 progress - download_progress_ >= kDeltaPercent ||
291 TimeTicks::Now() - last_notify_time_ >= TimeDelta::FromSeconds(10)) {
292 download_progress_ = progress;
293 SetStatusAndNotify(UpdateStatus::DOWNLOADING);
294 }
295}
296
297bool UpdateAttempterAndroid::ShouldCancel(ErrorCode* cancel_reason) {
298 // TODO(deymo): Notify the DownloadAction that it should cancel the update
299 // download.
300 return false;
301}
302
303void UpdateAttempterAndroid::DownloadComplete() {
304 // Nothing needs to be done when the download completes.
305}
306
307void UpdateAttempterAndroid::UpdateBootFlags() {
308 if (updated_boot_flags_) {
309 LOG(INFO) << "Already updated boot flags. Skipping.";
310 CompleteUpdateBootFlags(true);
311 return;
312 }
313 // This is purely best effort.
314 LOG(INFO) << "Marking booted slot as good.";
315 if (!boot_control_->MarkBootSuccessfulAsync(
316 Bind(&UpdateAttempterAndroid::CompleteUpdateBootFlags,
317 base::Unretained(this)))) {
318 LOG(ERROR) << "Failed to mark current boot as successful.";
319 CompleteUpdateBootFlags(false);
320 }
321}
322
323void UpdateAttempterAndroid::CompleteUpdateBootFlags(bool successful) {
324 updated_boot_flags_ = true;
325 ScheduleProcessingStart();
326}
327
328void UpdateAttempterAndroid::ScheduleProcessingStart() {
329 LOG(INFO) << "Scheduling an action processor start.";
330 brillo::MessageLoop::current()->PostTask(
331 FROM_HERE, Bind([this] { this->processor_->StartProcessing(); }));
332}
333
334void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
335 if (status_ == UpdateStatus::IDLE) {
336 LOG(ERROR) << "No ongoing update, but TerminatedUpdate() called.";
337 return;
338 }
339
340 // Reset cpu shares back to normal.
341 cpu_limiter_.StopLimiter();
342 download_progress_ = 0.0;
343 actions_.clear();
344 UpdateStatus new_status =
345 (error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
346 : UpdateStatus::IDLE);
347 SetStatusAndNotify(new_status);
348 ongoing_update_ = false;
349
350 for (auto observer : daemon_state_->service_observers())
351 observer->SendPayloadApplicationComplete(error_code);
352}
353
354void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
355 status_ = status;
356 for (auto observer : daemon_state_->service_observers()) {
357 observer->SendStatusUpdate(
358 0, download_progress_, status_, "", install_plan_.payload_size);
359 }
360 last_notify_time_ = TimeTicks::Now();
361}
362
363void UpdateAttempterAndroid::BuildUpdateActions() {
364 CHECK(!processor_->IsRunning());
365 processor_->set_delegate(this);
366
367 // Actions:
368 shared_ptr<InstallPlanAction> install_plan_action(
369 new InstallPlanAction(install_plan_));
370
371 LibcurlHttpFetcher* download_fetcher =
372 new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
373 download_fetcher->set_server_to_check(ServerToCheck::kDownload);
374 shared_ptr<DownloadAction> download_action(new DownloadAction(
375 prefs_,
376 boot_control_,
377 hardware_,
378 nullptr, // system_state, not used.
379 new MultiRangeHttpFetcher(download_fetcher))); // passes ownership
380 shared_ptr<FilesystemVerifierAction> dst_filesystem_verifier_action(
381 new FilesystemVerifierAction(boot_control_,
382 VerifierMode::kVerifyTargetHash));
383
384 shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
385 new PostinstallRunnerAction(boot_control_));
386
387 download_action->set_delegate(this);
388 download_action_ = download_action;
389
390 actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
391 actions_.push_back(shared_ptr<AbstractAction>(download_action));
392 actions_.push_back(
393 shared_ptr<AbstractAction>(dst_filesystem_verifier_action));
394 actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
395
396 // Bond them together. We have to use the leaf-types when calling
397 // BondActions().
398 BondActions(install_plan_action.get(), download_action.get());
399 BondActions(download_action.get(), dst_filesystem_verifier_action.get());
400 BondActions(dst_filesystem_verifier_action.get(),
401 postinstall_runner_action.get());
402
403 // Enqueue the actions.
404 for (const shared_ptr<AbstractAction>& action : actions_)
405 processor_->EnqueueAction(action.get());
406}
407
408void UpdateAttempterAndroid::SetupDownload() {
409 MultiRangeHttpFetcher* fetcher =
410 static_cast<MultiRangeHttpFetcher*>(download_action_->http_fetcher());
411 fetcher->ClearRanges();
412 if (install_plan_.is_resume) {
413 // Resuming an update so fetch the update manifest metadata first.
414 int64_t manifest_metadata_size = 0;
415 prefs_->GetInt64(kPrefsManifestMetadataSize, &manifest_metadata_size);
Alex Deymo0fd51ff2016-02-03 14:22:43 -0800416 fetcher->AddRange(base_offset_, manifest_metadata_size);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800417 // If there're remaining unprocessed data blobs, fetch them. Be careful not
418 // to request data beyond the end of the payload to avoid 416 HTTP response
419 // error codes.
420 int64_t next_data_offset = 0;
421 prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, &next_data_offset);
422 uint64_t resume_offset = manifest_metadata_size + next_data_offset;
Alex Deymo0fd51ff2016-02-03 14:22:43 -0800423 if (!install_plan_.payload_size) {
424 fetcher->AddRange(base_offset_ + resume_offset);
425 } else if (resume_offset < install_plan_.payload_size) {
426 fetcher->AddRange(base_offset_ + resume_offset,
427 install_plan_.payload_size - resume_offset);
Alex Deymo5e3ea272016-01-28 13:42:23 -0800428 }
429 } else {
Alex Deymo0fd51ff2016-02-03 14:22:43 -0800430 if (install_plan_.payload_size) {
431 fetcher->AddRange(base_offset_, install_plan_.payload_size);
432 } else {
433 // If no payload size is passed we assume we read until the end of the
434 // stream.
435 fetcher->AddRange(base_offset_);
436 }
Alex Deymo5e3ea272016-01-28 13:42:23 -0800437 }
438}
439
440bool UpdateAttempterAndroid::WriteUpdateCompletedMarker() {
441 string boot_id;
442 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
443 prefs_->SetString(kPrefsUpdateCompletedOnBootId, boot_id);
444 return true;
445}
446
447bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() {
448 // In case of an update_engine restart without a reboot, we stored the boot_id
449 // when the update was completed by setting a pref, so we can check whether
450 // the last update was on this boot or a previous one.
451 string boot_id;
452 TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));
453
454 string update_completed_on_boot_id;
455 return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
456 prefs_->GetString(kPrefsUpdateCompletedOnBootId,
457 &update_completed_on_boot_id) &&
458 update_completed_on_boot_id == boot_id);
459}
460
461} // namespace chromeos_update_engine