blob: 6e297c853d1c6e57761e5d1b4a47173baea2804f [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2014 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//
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070016
Alex Deymo63784a52014-05-28 10:46:14 -070017#include "update_engine/update_manager/real_updater_provider.h"
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070018
19#include <inttypes.h>
20
21#include <string>
22
Gilad Arnold44dc3bf2014-07-18 23:39:38 -070023#include <base/bind.h>
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070024#include <base/strings/stringprintf.h>
Alex Deymoc7ab6162014-04-25 18:32:50 -070025#include <base/time/time.h>
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070026#include <chromeos/dbus/service_constants.h>
27
28#include "update_engine/clock_interface.h"
29#include "update_engine/omaha_request_params.h"
30#include "update_engine/prefs.h"
31#include "update_engine/update_attempter.h"
32
33using base::StringPrintf;
34using base::Time;
35using base::TimeDelta;
36using chromeos_update_engine::OmahaRequestParams;
37using chromeos_update_engine::SystemState;
38using std::string;
39
Alex Deymo63784a52014-05-28 10:46:14 -070040namespace chromeos_update_manager {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070041
42// A templated base class for all update related variables. Provides uniform
43// construction and a system state handle.
44template<typename T>
45class UpdaterVariableBase : public Variable<T> {
46 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -070047 UpdaterVariableBase(const string& name, VariableMode mode,
48 SystemState* system_state)
49 : Variable<T>(name, mode), system_state_(system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070050
51 protected:
52 // The system state used for pulling information from the updater.
53 inline SystemState* system_state() const { return system_state_; }
54
55 private:
56 SystemState* const system_state_;
57};
58
59// Helper class for issuing a GetStatus() to the UpdateAttempter.
60class GetStatusHelper {
61 public:
62 GetStatusHelper(SystemState* system_state, string* errmsg) {
63 is_success_ = system_state->update_attempter()->GetStatus(
64 &last_checked_time_, &progress_, &update_status_, &new_version_,
65 &payload_size_);
66 if (!is_success_ && errmsg)
67 *errmsg = "Failed to get a status update from the update engine";
68 }
69
70 inline bool is_success() { return is_success_; }
71 inline int64_t last_checked_time() { return last_checked_time_; }
72 inline double progress() { return progress_; }
73 inline const string& update_status() { return update_status_; }
74 inline const string& new_version() { return new_version_; }
75 inline int64_t payload_size() { return payload_size_; }
76
77 private:
78 bool is_success_;
79 int64_t last_checked_time_;
80 double progress_;
81 string update_status_;
82 string new_version_;
83 int64_t payload_size_;
84};
85
86// A variable reporting the time when a last update check was issued.
87class LastCheckedTimeVariable : public UpdaterVariableBase<Time> {
88 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -070089 LastCheckedTimeVariable(const string& name, SystemState* system_state)
90 : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070091
92 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -070093 const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070094 GetStatusHelper raw(system_state(), errmsg);
95 if (!raw.is_success())
Alex Vakulenko88b591f2014-08-28 16:48:57 -070096 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070097
98 return new Time(Time::FromTimeT(raw.last_checked_time()));
99 }
100
101 DISALLOW_COPY_AND_ASSIGN(LastCheckedTimeVariable);
102};
103
104// A variable reporting the update (download) progress as a decimal fraction
105// between 0.0 and 1.0.
106class ProgressVariable : public UpdaterVariableBase<double> {
107 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700108 ProgressVariable(const string& name, SystemState* system_state)
109 : UpdaterVariableBase<double>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700110
111 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700112 const double* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700113 GetStatusHelper raw(system_state(), errmsg);
114 if (!raw.is_success())
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700115 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700116
117 if (raw.progress() < 0.0 || raw.progress() > 1.0) {
118 if (errmsg) {
119 *errmsg = StringPrintf("Invalid progress value received: %f",
120 raw.progress());
121 }
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700122 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700123 }
124
125 return new double(raw.progress());
126 }
127
128 DISALLOW_COPY_AND_ASSIGN(ProgressVariable);
129};
130
131// A variable reporting the stage in which the update process is.
132class StageVariable : public UpdaterVariableBase<Stage> {
133 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700134 StageVariable(const string& name, SystemState* system_state)
135 : UpdaterVariableBase<Stage>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700136
137 private:
138 struct CurrOpStrToStage {
139 const char* str;
140 Stage stage;
141 };
142 static const CurrOpStrToStage curr_op_str_to_stage[];
143
144 // Note: the method is defined outside the class so arraysize can work.
Alex Vakulenko157fe302014-08-11 15:59:58 -0700145 const Stage* GetValue(TimeDelta /* timeout */, string* errmsg) override;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700146
147 DISALLOW_COPY_AND_ASSIGN(StageVariable);
148};
149
150const StageVariable::CurrOpStrToStage StageVariable::curr_op_str_to_stage[] = {
151 {update_engine::kUpdateStatusIdle, Stage::kIdle},
152 {update_engine::kUpdateStatusCheckingForUpdate, Stage::kCheckingForUpdate},
153 {update_engine::kUpdateStatusUpdateAvailable, Stage::kUpdateAvailable},
154 {update_engine::kUpdateStatusDownloading, Stage::kDownloading},
155 {update_engine::kUpdateStatusVerifying, Stage::kVerifying},
156 {update_engine::kUpdateStatusFinalizing, Stage::kFinalizing},
157 {update_engine::kUpdateStatusUpdatedNeedReboot, Stage::kUpdatedNeedReboot},
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700158 { // NOLINT(whitespace/braces)
159 update_engine::kUpdateStatusReportingErrorEvent,
160 Stage::kReportingErrorEvent
161 },
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700162 {update_engine::kUpdateStatusAttemptingRollback, Stage::kAttemptingRollback},
163};
164
165const Stage* StageVariable::GetValue(TimeDelta /* timeout */,
166 string* errmsg) {
167 GetStatusHelper raw(system_state(), errmsg);
168 if (!raw.is_success())
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700169 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700170
171 for (auto& key_val : curr_op_str_to_stage)
172 if (raw.update_status() == key_val.str)
173 return new Stage(key_val.stage);
174
175 if (errmsg)
176 *errmsg = string("Unknown update status: ") + raw.update_status();
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700177 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700178}
179
180// A variable reporting the version number that an update is updating to.
181class NewVersionVariable : public UpdaterVariableBase<string> {
182 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700183 NewVersionVariable(const string& name, SystemState* system_state)
184 : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700185
186 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700187 const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700188 GetStatusHelper raw(system_state(), errmsg);
189 if (!raw.is_success())
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700190 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700191
192 return new string(raw.new_version());
193 }
194
195 DISALLOW_COPY_AND_ASSIGN(NewVersionVariable);
196};
197
198// A variable reporting the size of the update being processed in bytes.
Alex Deymof967ebe2014-05-05 14:46:17 -0700199class PayloadSizeVariable : public UpdaterVariableBase<int64_t> {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700200 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700201 PayloadSizeVariable(const string& name, SystemState* system_state)
202 : UpdaterVariableBase<int64_t>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700203
204 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700205 const int64_t* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700206 GetStatusHelper raw(system_state(), errmsg);
207 if (!raw.is_success())
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700208 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700209
210 if (raw.payload_size() < 0) {
211 if (errmsg)
212 *errmsg = string("Invalid payload size: %" PRId64, raw.payload_size());
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700213 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700214 }
215
Alex Deymof967ebe2014-05-05 14:46:17 -0700216 return new int64_t(raw.payload_size());
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700217 }
218
219 DISALLOW_COPY_AND_ASSIGN(PayloadSizeVariable);
220};
221
222// A variable reporting the point in time an update last completed in the
223// current boot cycle.
224//
225// TODO(garnold) In general, both the current boottime and wallclock time
226// readings should come from the time provider and be moderated by the
227// evaluation context, so that they are uniform throughout the evaluation of a
228// policy request.
229class UpdateCompletedTimeVariable : public UpdaterVariableBase<Time> {
230 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700231 UpdateCompletedTimeVariable(const string& name, SystemState* system_state)
232 : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700233
234 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700235 const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700236 Time update_boottime;
237 if (!system_state()->update_attempter()->GetBootTimeAtUpdate(
238 &update_boottime)) {
239 if (errmsg)
240 *errmsg = "Update completed time could not be read";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700241 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700242 }
243
244 chromeos_update_engine::ClockInterface* clock = system_state()->clock();
245 Time curr_boottime = clock->GetBootTime();
246 if (curr_boottime < update_boottime) {
247 if (errmsg)
248 *errmsg = "Update completed time more recent than current time";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700249 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700250 }
251 TimeDelta duration_since_update = curr_boottime - update_boottime;
252 return new Time(clock->GetWallclockTime() - duration_since_update);
253 }
254
255 DISALLOW_COPY_AND_ASSIGN(UpdateCompletedTimeVariable);
256};
257
258// Variables reporting the current image channel.
259class CurrChannelVariable : public UpdaterVariableBase<string> {
260 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700261 CurrChannelVariable(const string& name, SystemState* system_state)
262 : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700263
264 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700265 const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700266 OmahaRequestParams* request_params = system_state()->request_params();
267 string channel = request_params->current_channel();
268 if (channel.empty()) {
269 if (errmsg)
270 *errmsg = "No current channel";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700271 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700272 }
273 return new string(channel);
274 }
275
276 DISALLOW_COPY_AND_ASSIGN(CurrChannelVariable);
277};
278
279// Variables reporting the new image channel.
280class NewChannelVariable : public UpdaterVariableBase<string> {
281 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700282 NewChannelVariable(const string& name, SystemState* system_state)
283 : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700284
285 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700286 const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700287 OmahaRequestParams* request_params = system_state()->request_params();
288 string channel = request_params->target_channel();
289 if (channel.empty()) {
290 if (errmsg)
291 *errmsg = "No new channel";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700292 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700293 }
294 return new string(channel);
295 }
296
297 DISALLOW_COPY_AND_ASSIGN(NewChannelVariable);
298};
299
300// A variable class for reading Boolean prefs values.
301class BooleanPrefVariable : public UpdaterVariableBase<bool> {
302 public:
303 BooleanPrefVariable(const string& name, SystemState* system_state,
304 const char* key, bool default_val)
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700305 : UpdaterVariableBase<bool>(name, kVariableModePoll, system_state),
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700306 key_(key), default_val_(default_val) {}
307
308 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700309 const bool* GetValue(TimeDelta /* timeout */, string* errmsg) override {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700310 bool result = default_val_;
311 chromeos_update_engine::PrefsInterface* prefs = system_state()->prefs();
312 if (prefs && prefs->Exists(key_) && !prefs->GetBoolean(key_, &result)) {
313 if (errmsg)
314 *errmsg = string("Could not read boolean pref ") + key_;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700315 return nullptr;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700316 }
317 return new bool(result);
318 }
319
320 // The Boolean preference key and default value.
321 const char* const key_;
322 const bool default_val_;
323
324 DISALLOW_COPY_AND_ASSIGN(BooleanPrefVariable);
325};
326
Gilad Arnolda6dab942014-04-25 11:46:03 -0700327// A variable returning the number of consecutive failed update checks.
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700328class ConsecutiveFailedUpdateChecksVariable
329 : public UpdaterVariableBase<unsigned int> {
Gilad Arnolda6dab942014-04-25 11:46:03 -0700330 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700331 ConsecutiveFailedUpdateChecksVariable(const string& name,
332 SystemState* system_state)
333 : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
334 system_state) {}
Gilad Arnolda6dab942014-04-25 11:46:03 -0700335
336 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700337 const unsigned int* GetValue(TimeDelta /* timeout */,
338 string* /* errmsg */) override {
Gilad Arnolda6dab942014-04-25 11:46:03 -0700339 return new unsigned int(
340 system_state()->update_attempter()->consecutive_failed_update_checks());
341 }
342
343 DISALLOW_COPY_AND_ASSIGN(ConsecutiveFailedUpdateChecksVariable);
344};
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700345
Gilad Arnolda0258a52014-07-10 16:21:19 -0700346// A variable returning the server-dictated poll interval.
347class ServerDictatedPollIntervalVariable
348 : public UpdaterVariableBase<unsigned int> {
349 public:
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700350 ServerDictatedPollIntervalVariable(const string& name,
351 SystemState* system_state)
352 : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
353 system_state) {}
Gilad Arnolda0258a52014-07-10 16:21:19 -0700354
355 private:
Alex Vakulenko157fe302014-08-11 15:59:58 -0700356 const unsigned int* GetValue(TimeDelta /* timeout */,
357 string* /* errmsg */) override {
Gilad Arnolda0258a52014-07-10 16:21:19 -0700358 return new unsigned int(
359 system_state()->update_attempter()->server_dictated_poll_interval());
360 }
361
362 DISALLOW_COPY_AND_ASSIGN(ServerDictatedPollIntervalVariable);
363};
364
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700365// An async variable that tracks changes to forced update requests.
366class ForcedUpdateRequestedVariable
367 : public UpdaterVariableBase<UpdateRequestStatus> {
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700368 public:
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700369 ForcedUpdateRequestedVariable(const string& name, SystemState* system_state)
370 : UpdaterVariableBase<UpdateRequestStatus>::UpdaterVariableBase(
371 name, kVariableModeAsync, system_state) {
372 system_state->update_attempter()->set_forced_update_pending_callback(
373 new base::Callback<void(bool, bool)>( // NOLINT(readability/function)
374 base::Bind(&ForcedUpdateRequestedVariable::Reset,
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700375 base::Unretained(this))));
376 }
377
378 private:
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700379 const UpdateRequestStatus* GetValue(TimeDelta /* timeout */,
380 string* /* errmsg */) override {
381 return new UpdateRequestStatus(update_request_status_);
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700382 }
383
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700384 void Reset(bool forced_update_requested, bool is_interactive) {
385 UpdateRequestStatus new_value = UpdateRequestStatus::kNone;
386 if (forced_update_requested)
387 new_value = (is_interactive ? UpdateRequestStatus::kInteractive :
388 UpdateRequestStatus::kPeriodic);
389 if (update_request_status_ != new_value) {
390 update_request_status_ = new_value;
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700391 NotifyValueChanged();
392 }
393 }
394
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700395 UpdateRequestStatus update_request_status_ = UpdateRequestStatus::kNone;
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700396
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700397 DISALLOW_COPY_AND_ASSIGN(ForcedUpdateRequestedVariable);
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700398};
399
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700400// RealUpdaterProvider methods.
401
402RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
403 : system_state_(system_state),
Alex Deymoc7ab6162014-04-25 18:32:50 -0700404 var_updater_started_time_("updater_started_time",
405 system_state->clock()->GetWallclockTime()),
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700406 var_last_checked_time_(
407 new LastCheckedTimeVariable("last_checked_time", system_state_)),
408 var_update_completed_time_(
409 new UpdateCompletedTimeVariable("update_completed_time",
410 system_state_)),
411 var_progress_(new ProgressVariable("progress", system_state_)),
412 var_stage_(new StageVariable("stage", system_state_)),
413 var_new_version_(new NewVersionVariable("new_version", system_state_)),
414 var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
415 var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
416 var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
417 var_p2p_enabled_(
418 new BooleanPrefVariable("p2p_enabled", system_state_,
419 chromeos_update_engine::kPrefsP2PEnabled,
420 false)),
421 var_cellular_enabled_(
422 new BooleanPrefVariable(
423 "cellular_enabled", system_state_,
424 chromeos_update_engine::kPrefsUpdateOverCellularPermission,
Gilad Arnolda6dab942014-04-25 11:46:03 -0700425 false)),
426 var_consecutive_failed_update_checks_(
427 new ConsecutiveFailedUpdateChecksVariable(
Gilad Arnolda0258a52014-07-10 16:21:19 -0700428 "consecutive_failed_update_checks", system_state_)),
429 var_server_dictated_poll_interval_(
430 new ServerDictatedPollIntervalVariable(
Gilad Arnold44dc3bf2014-07-18 23:39:38 -0700431 "server_dictated_poll_interval", system_state_)),
Gilad Arnoldec7f9162014-07-15 13:24:46 -0700432 var_forced_update_requested_(
433 new ForcedUpdateRequestedVariable(
434 "forced_update_requested", system_state_)) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700435
Alex Deymo63784a52014-05-28 10:46:14 -0700436} // namespace chromeos_update_manager