blob: 47d5dfa84ba7ad1ea2e8581856ce3f6e0ea8fa03 [file] [log] [blame]
Gilad Arnoldae47a9a2014-03-26 12:16:47 -07001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymo63784a52014-05-28 10:46:14 -07005#include "update_engine/update_manager/real_updater_provider.h"
Gilad Arnoldae47a9a2014-03-26 12:16:47 -07006
7#include <inttypes.h>
8
9#include <string>
10
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070011#include <base/strings/stringprintf.h>
Alex Deymoc7ab6162014-04-25 18:32:50 -070012#include <base/time/time.h>
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070013#include <chromeos/dbus/service_constants.h>
14
15#include "update_engine/clock_interface.h"
16#include "update_engine/omaha_request_params.h"
17#include "update_engine/prefs.h"
18#include "update_engine/update_attempter.h"
19
20using base::StringPrintf;
21using base::Time;
22using base::TimeDelta;
23using chromeos_update_engine::OmahaRequestParams;
24using chromeos_update_engine::SystemState;
25using std::string;
26
Alex Deymo63784a52014-05-28 10:46:14 -070027namespace chromeos_update_manager {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -070028
29// A templated base class for all update related variables. Provides uniform
30// construction and a system state handle.
31template<typename T>
32class UpdaterVariableBase : public Variable<T> {
33 public:
34 UpdaterVariableBase(const string& name, SystemState* system_state)
35 : Variable<T>(name, kVariableModePoll), system_state_(system_state) {}
36
37 protected:
38 // The system state used for pulling information from the updater.
39 inline SystemState* system_state() const { return system_state_; }
40
41 private:
42 SystemState* const system_state_;
43};
44
45// Helper class for issuing a GetStatus() to the UpdateAttempter.
46class GetStatusHelper {
47 public:
48 GetStatusHelper(SystemState* system_state, string* errmsg) {
49 is_success_ = system_state->update_attempter()->GetStatus(
50 &last_checked_time_, &progress_, &update_status_, &new_version_,
51 &payload_size_);
52 if (!is_success_ && errmsg)
53 *errmsg = "Failed to get a status update from the update engine";
54 }
55
56 inline bool is_success() { return is_success_; }
57 inline int64_t last_checked_time() { return last_checked_time_; }
58 inline double progress() { return progress_; }
59 inline const string& update_status() { return update_status_; }
60 inline const string& new_version() { return new_version_; }
61 inline int64_t payload_size() { return payload_size_; }
62
63 private:
64 bool is_success_;
65 int64_t last_checked_time_;
66 double progress_;
67 string update_status_;
68 string new_version_;
69 int64_t payload_size_;
70};
71
72// A variable reporting the time when a last update check was issued.
73class LastCheckedTimeVariable : public UpdaterVariableBase<Time> {
74 public:
75 using UpdaterVariableBase<Time>::UpdaterVariableBase;
76
77 private:
78 virtual const Time* GetValue(TimeDelta /* timeout */,
79 string* errmsg) override {
80 GetStatusHelper raw(system_state(), errmsg);
81 if (!raw.is_success())
82 return NULL;
83
84 return new Time(Time::FromTimeT(raw.last_checked_time()));
85 }
86
87 DISALLOW_COPY_AND_ASSIGN(LastCheckedTimeVariable);
88};
89
90// A variable reporting the update (download) progress as a decimal fraction
91// between 0.0 and 1.0.
92class ProgressVariable : public UpdaterVariableBase<double> {
93 public:
94 using UpdaterVariableBase<double>::UpdaterVariableBase;
95
96 private:
97 virtual const double* GetValue(TimeDelta /* timeout */,
98 string* errmsg) override {
99 GetStatusHelper raw(system_state(), errmsg);
100 if (!raw.is_success())
101 return NULL;
102
103 if (raw.progress() < 0.0 || raw.progress() > 1.0) {
104 if (errmsg) {
105 *errmsg = StringPrintf("Invalid progress value received: %f",
106 raw.progress());
107 }
108 return NULL;
109 }
110
111 return new double(raw.progress());
112 }
113
114 DISALLOW_COPY_AND_ASSIGN(ProgressVariable);
115};
116
117// A variable reporting the stage in which the update process is.
118class StageVariable : public UpdaterVariableBase<Stage> {
119 public:
120 using UpdaterVariableBase<Stage>::UpdaterVariableBase;
121
122 private:
123 struct CurrOpStrToStage {
124 const char* str;
125 Stage stage;
126 };
127 static const CurrOpStrToStage curr_op_str_to_stage[];
128
129 // Note: the method is defined outside the class so arraysize can work.
130 virtual const Stage* GetValue(TimeDelta /* timeout */,
131 string* errmsg) override;
132
133 DISALLOW_COPY_AND_ASSIGN(StageVariable);
134};
135
136const StageVariable::CurrOpStrToStage StageVariable::curr_op_str_to_stage[] = {
137 {update_engine::kUpdateStatusIdle, Stage::kIdle},
138 {update_engine::kUpdateStatusCheckingForUpdate, Stage::kCheckingForUpdate},
139 {update_engine::kUpdateStatusUpdateAvailable, Stage::kUpdateAvailable},
140 {update_engine::kUpdateStatusDownloading, Stage::kDownloading},
141 {update_engine::kUpdateStatusVerifying, Stage::kVerifying},
142 {update_engine::kUpdateStatusFinalizing, Stage::kFinalizing},
143 {update_engine::kUpdateStatusUpdatedNeedReboot, Stage::kUpdatedNeedReboot},
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700144 { // NOLINT(whitespace/braces)
145 update_engine::kUpdateStatusReportingErrorEvent,
146 Stage::kReportingErrorEvent
147 },
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700148 {update_engine::kUpdateStatusAttemptingRollback, Stage::kAttemptingRollback},
149};
150
151const Stage* StageVariable::GetValue(TimeDelta /* timeout */,
152 string* errmsg) {
153 GetStatusHelper raw(system_state(), errmsg);
154 if (!raw.is_success())
155 return NULL;
156
157 for (auto& key_val : curr_op_str_to_stage)
158 if (raw.update_status() == key_val.str)
159 return new Stage(key_val.stage);
160
161 if (errmsg)
162 *errmsg = string("Unknown update status: ") + raw.update_status();
163 return NULL;
164}
165
166// A variable reporting the version number that an update is updating to.
167class NewVersionVariable : public UpdaterVariableBase<string> {
168 public:
169 using UpdaterVariableBase<string>::UpdaterVariableBase;
170
171 private:
172 virtual const string* GetValue(TimeDelta /* timeout */,
173 string* errmsg) override {
174 GetStatusHelper raw(system_state(), errmsg);
175 if (!raw.is_success())
176 return NULL;
177
178 return new string(raw.new_version());
179 }
180
181 DISALLOW_COPY_AND_ASSIGN(NewVersionVariable);
182};
183
184// A variable reporting the size of the update being processed in bytes.
Alex Deymof967ebe2014-05-05 14:46:17 -0700185class PayloadSizeVariable : public UpdaterVariableBase<int64_t> {
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700186 public:
Alex Deymof967ebe2014-05-05 14:46:17 -0700187 using UpdaterVariableBase<int64_t>::UpdaterVariableBase;
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700188
189 private:
Alex Deymof967ebe2014-05-05 14:46:17 -0700190 virtual const int64_t* GetValue(TimeDelta /* timeout */,
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700191 string* errmsg) override {
192 GetStatusHelper raw(system_state(), errmsg);
193 if (!raw.is_success())
194 return NULL;
195
196 if (raw.payload_size() < 0) {
197 if (errmsg)
198 *errmsg = string("Invalid payload size: %" PRId64, raw.payload_size());
199 return NULL;
200 }
201
Alex Deymof967ebe2014-05-05 14:46:17 -0700202 return new int64_t(raw.payload_size());
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700203 }
204
205 DISALLOW_COPY_AND_ASSIGN(PayloadSizeVariable);
206};
207
208// A variable reporting the point in time an update last completed in the
209// current boot cycle.
210//
211// TODO(garnold) In general, both the current boottime and wallclock time
212// readings should come from the time provider and be moderated by the
213// evaluation context, so that they are uniform throughout the evaluation of a
214// policy request.
215class UpdateCompletedTimeVariable : public UpdaterVariableBase<Time> {
216 public:
217 using UpdaterVariableBase<Time>::UpdaterVariableBase;
218
219 private:
220 virtual const Time* GetValue(TimeDelta /* timeout */,
221 string* errmsg) override {
222 Time update_boottime;
223 if (!system_state()->update_attempter()->GetBootTimeAtUpdate(
224 &update_boottime)) {
225 if (errmsg)
226 *errmsg = "Update completed time could not be read";
227 return NULL;
228 }
229
230 chromeos_update_engine::ClockInterface* clock = system_state()->clock();
231 Time curr_boottime = clock->GetBootTime();
232 if (curr_boottime < update_boottime) {
233 if (errmsg)
234 *errmsg = "Update completed time more recent than current time";
235 return NULL;
236 }
237 TimeDelta duration_since_update = curr_boottime - update_boottime;
238 return new Time(clock->GetWallclockTime() - duration_since_update);
239 }
240
241 DISALLOW_COPY_AND_ASSIGN(UpdateCompletedTimeVariable);
242};
243
244// Variables reporting the current image channel.
245class CurrChannelVariable : public UpdaterVariableBase<string> {
246 public:
247 using UpdaterVariableBase<string>::UpdaterVariableBase;
248
249 private:
250 virtual const string* GetValue(TimeDelta /* timeout */,
251 string* errmsg) override {
252 OmahaRequestParams* request_params = system_state()->request_params();
253 string channel = request_params->current_channel();
254 if (channel.empty()) {
255 if (errmsg)
256 *errmsg = "No current channel";
257 return NULL;
258 }
259 return new string(channel);
260 }
261
262 DISALLOW_COPY_AND_ASSIGN(CurrChannelVariable);
263};
264
265// Variables reporting the new image channel.
266class NewChannelVariable : public UpdaterVariableBase<string> {
267 public:
268 using UpdaterVariableBase<string>::UpdaterVariableBase;
269
270 private:
271 virtual const string* GetValue(TimeDelta /* timeout */,
272 string* errmsg) override {
273 OmahaRequestParams* request_params = system_state()->request_params();
274 string channel = request_params->target_channel();
275 if (channel.empty()) {
276 if (errmsg)
277 *errmsg = "No new channel";
278 return NULL;
279 }
280 return new string(channel);
281 }
282
283 DISALLOW_COPY_AND_ASSIGN(NewChannelVariable);
284};
285
286// A variable class for reading Boolean prefs values.
287class BooleanPrefVariable : public UpdaterVariableBase<bool> {
288 public:
289 BooleanPrefVariable(const string& name, SystemState* system_state,
290 const char* key, bool default_val)
291 : UpdaterVariableBase<bool>(name, system_state),
292 key_(key), default_val_(default_val) {}
293
294 private:
295 virtual const bool* GetValue(TimeDelta /* timeout */,
296 string* errmsg) override {
297 bool result = default_val_;
298 chromeos_update_engine::PrefsInterface* prefs = system_state()->prefs();
299 if (prefs && prefs->Exists(key_) && !prefs->GetBoolean(key_, &result)) {
300 if (errmsg)
301 *errmsg = string("Could not read boolean pref ") + key_;
302 return NULL;
303 }
304 return new bool(result);
305 }
306
307 // The Boolean preference key and default value.
308 const char* const key_;
309 const bool default_val_;
310
311 DISALLOW_COPY_AND_ASSIGN(BooleanPrefVariable);
312};
313
Gilad Arnolda6dab942014-04-25 11:46:03 -0700314// A variable returning the number of consecutive failed update checks.
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700315class ConsecutiveFailedUpdateChecksVariable
316 : public UpdaterVariableBase<unsigned int> {
Gilad Arnolda6dab942014-04-25 11:46:03 -0700317 public:
318 using UpdaterVariableBase<unsigned int>::UpdaterVariableBase;
319
320 private:
321 virtual const unsigned int* GetValue(TimeDelta /* timeout */,
322 string* /* errmsg */) override {
323 return new unsigned int(
324 system_state()->update_attempter()->consecutive_failed_update_checks());
325 }
326
327 DISALLOW_COPY_AND_ASSIGN(ConsecutiveFailedUpdateChecksVariable);
328};
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700329
Gilad Arnolda0258a52014-07-10 16:21:19 -0700330// A variable returning the server-dictated poll interval.
331class ServerDictatedPollIntervalVariable
332 : public UpdaterVariableBase<unsigned int> {
333 public:
334 using UpdaterVariableBase<unsigned int>::UpdaterVariableBase;
335
336 private:
337 virtual const unsigned int* GetValue(TimeDelta /* timeout */,
338 string* /* errmsg */) override {
339 return new unsigned int(
340 system_state()->update_attempter()->server_dictated_poll_interval());
341 }
342
343 DISALLOW_COPY_AND_ASSIGN(ServerDictatedPollIntervalVariable);
344};
345
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700346// RealUpdaterProvider methods.
347
348RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
349 : system_state_(system_state),
Alex Deymoc7ab6162014-04-25 18:32:50 -0700350 var_updater_started_time_("updater_started_time",
351 system_state->clock()->GetWallclockTime()),
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700352 var_last_checked_time_(
353 new LastCheckedTimeVariable("last_checked_time", system_state_)),
354 var_update_completed_time_(
355 new UpdateCompletedTimeVariable("update_completed_time",
356 system_state_)),
357 var_progress_(new ProgressVariable("progress", system_state_)),
358 var_stage_(new StageVariable("stage", system_state_)),
359 var_new_version_(new NewVersionVariable("new_version", system_state_)),
360 var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
361 var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
362 var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
363 var_p2p_enabled_(
364 new BooleanPrefVariable("p2p_enabled", system_state_,
365 chromeos_update_engine::kPrefsP2PEnabled,
366 false)),
367 var_cellular_enabled_(
368 new BooleanPrefVariable(
369 "cellular_enabled", system_state_,
370 chromeos_update_engine::kPrefsUpdateOverCellularPermission,
Gilad Arnolda6dab942014-04-25 11:46:03 -0700371 false)),
372 var_consecutive_failed_update_checks_(
373 new ConsecutiveFailedUpdateChecksVariable(
Gilad Arnolda0258a52014-07-10 16:21:19 -0700374 "consecutive_failed_update_checks", system_state_)),
375 var_server_dictated_poll_interval_(
376 new ServerDictatedPollIntervalVariable(
377 "server_dictated_poll_interval", system_state_)) {}
Gilad Arnoldae47a9a2014-03-26 12:16:47 -0700378
Alex Deymo63784a52014-05-28 10:46:14 -0700379} // namespace chromeos_update_manager