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