1 //
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 //
16
17 #include "update_engine/update_manager/real_updater_provider.h"
18
19 #include <inttypes.h>
20
21 #include <string>
22
23 #include <base/bind.h>
24 #include <base/strings/stringprintf.h>
25 #include <base/time/time.h>
26 #include <update_engine/dbus-constants.h>
27
28 #include "update_engine/client_library/include/update_engine/update_status.h"
29 #include "update_engine/common/clock_interface.h"
30 #include "update_engine/common/prefs.h"
31 #include "update_engine/omaha_request_params.h"
32 #include "update_engine/update_attempter.h"
33 #include "update_engine/update_status_utils.h"
34
35 using base::StringPrintf;
36 using base::Time;
37 using base::TimeDelta;
38 using chromeos_update_engine::OmahaRequestParams;
39 using chromeos_update_engine::SystemState;
40 using std::string;
41 using update_engine::UpdateAttemptFlags;
42 using update_engine::UpdateEngineStatus;
43
44 namespace chromeos_update_manager {
45
46 // A templated base class for all update related variables. Provides uniform
47 // construction and a system state handle.
48 template <typename T>
49 class UpdaterVariableBase : public Variable<T> {
50 public:
UpdaterVariableBase(const string & name,VariableMode mode,SystemState * system_state)51 UpdaterVariableBase(const string& name,
52 VariableMode mode,
53 SystemState* system_state)
54 : Variable<T>(name, mode), system_state_(system_state) {}
55
56 protected:
57 // The system state used for pulling information from the updater.
system_state() const58 inline SystemState* system_state() const { return system_state_; }
59
60 private:
61 SystemState* const system_state_;
62 };
63
64 // Helper class for issuing a GetStatus() to the UpdateAttempter.
65 class GetStatusHelper {
66 public:
GetStatusHelper(SystemState * system_state,string * errmsg)67 GetStatusHelper(SystemState* system_state, string* errmsg) {
68 is_success_ =
69 system_state->update_attempter()->GetStatus(&update_engine_status_);
70 if (!is_success_ && errmsg) {
71 *errmsg = "Failed to get a status update from the update engine";
72 }
73 }
74
is_success()75 inline bool is_success() { return is_success_; }
last_checked_time()76 inline int64_t last_checked_time() {
77 return update_engine_status_.last_checked_time;
78 }
progress()79 inline double progress() { return update_engine_status_.progress; }
update_status()80 inline const string update_status() {
81 return chromeos_update_engine::UpdateStatusToString(
82 update_engine_status_.status);
83 }
new_version()84 inline const string& new_version() {
85 return update_engine_status_.new_version;
86 }
payload_size()87 inline uint64_t payload_size() {
88 return update_engine_status_.new_size_bytes;
89 }
90
91 private:
92 bool is_success_;
93 UpdateEngineStatus update_engine_status_;
94 };
95
96 // A variable reporting the time when a last update check was issued.
97 class LastCheckedTimeVariable : public UpdaterVariableBase<Time> {
98 public:
LastCheckedTimeVariable(const string & name,SystemState * system_state)99 LastCheckedTimeVariable(const string& name, SystemState* system_state)
100 : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
101
102 private:
GetValue(TimeDelta,string * errmsg)103 const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
104 GetStatusHelper raw(system_state(), errmsg);
105 if (!raw.is_success())
106 return nullptr;
107
108 return new Time(Time::FromTimeT(raw.last_checked_time()));
109 }
110
111 DISALLOW_COPY_AND_ASSIGN(LastCheckedTimeVariable);
112 };
113
114 // A variable reporting the update (download) progress as a decimal fraction
115 // between 0.0 and 1.0.
116 class ProgressVariable : public UpdaterVariableBase<double> {
117 public:
ProgressVariable(const string & name,SystemState * system_state)118 ProgressVariable(const string& name, SystemState* system_state)
119 : UpdaterVariableBase<double>(name, kVariableModePoll, system_state) {}
120
121 private:
GetValue(TimeDelta,string * errmsg)122 const double* GetValue(TimeDelta /* timeout */, string* errmsg) override {
123 GetStatusHelper raw(system_state(), errmsg);
124 if (!raw.is_success())
125 return nullptr;
126
127 if (raw.progress() < 0.0 || raw.progress() > 1.0) {
128 if (errmsg) {
129 *errmsg =
130 StringPrintf("Invalid progress value received: %f", raw.progress());
131 }
132 return nullptr;
133 }
134
135 return new double(raw.progress());
136 }
137
138 DISALLOW_COPY_AND_ASSIGN(ProgressVariable);
139 };
140
141 // A variable reporting the stage in which the update process is.
142 class StageVariable : public UpdaterVariableBase<Stage> {
143 public:
StageVariable(const string & name,SystemState * system_state)144 StageVariable(const string& name, SystemState* system_state)
145 : UpdaterVariableBase<Stage>(name, kVariableModePoll, system_state) {}
146
147 private:
148 struct CurrOpStrToStage {
149 const char* str;
150 Stage stage;
151 };
152 static const CurrOpStrToStage curr_op_str_to_stage[];
153
154 // Note: the method is defined outside the class so arraysize can work.
155 const Stage* GetValue(TimeDelta /* timeout */, string* errmsg) override;
156
157 DISALLOW_COPY_AND_ASSIGN(StageVariable);
158 };
159
160 const StageVariable::CurrOpStrToStage StageVariable::curr_op_str_to_stage[] = {
161 {update_engine::kUpdateStatusIdle, Stage::kIdle},
162 {update_engine::kUpdateStatusCheckingForUpdate, Stage::kCheckingForUpdate},
163 {update_engine::kUpdateStatusUpdateAvailable, Stage::kUpdateAvailable},
164 {update_engine::kUpdateStatusDownloading, Stage::kDownloading},
165 {update_engine::kUpdateStatusVerifying, Stage::kVerifying},
166 {update_engine::kUpdateStatusFinalizing, Stage::kFinalizing},
167 {update_engine::kUpdateStatusUpdatedNeedReboot, Stage::kUpdatedNeedReboot},
168 {update_engine::kUpdateStatusReportingErrorEvent,
169 Stage::kReportingErrorEvent},
170 {update_engine::kUpdateStatusAttemptingRollback,
171 Stage::kAttemptingRollback},
172 };
173
GetValue(TimeDelta,string * errmsg)174 const Stage* StageVariable::GetValue(TimeDelta /* timeout */, string* errmsg) {
175 GetStatusHelper raw(system_state(), errmsg);
176 if (!raw.is_success())
177 return nullptr;
178
179 for (auto& key_val : curr_op_str_to_stage)
180 if (raw.update_status() == key_val.str)
181 return new Stage(key_val.stage);
182
183 if (errmsg)
184 *errmsg = string("Unknown update status: ") + raw.update_status();
185 return nullptr;
186 }
187
188 // A variable reporting the version number that an update is updating to.
189 class NewVersionVariable : public UpdaterVariableBase<string> {
190 public:
NewVersionVariable(const string & name,SystemState * system_state)191 NewVersionVariable(const string& name, SystemState* system_state)
192 : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
193
194 private:
GetValue(TimeDelta,string * errmsg)195 const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
196 GetStatusHelper raw(system_state(), errmsg);
197 if (!raw.is_success())
198 return nullptr;
199
200 return new string(raw.new_version());
201 }
202
203 DISALLOW_COPY_AND_ASSIGN(NewVersionVariable);
204 };
205
206 // A variable reporting the size of the update being processed in bytes.
207 class PayloadSizeVariable : public UpdaterVariableBase<uint64_t> {
208 public:
PayloadSizeVariable(const string & name,SystemState * system_state)209 PayloadSizeVariable(const string& name, SystemState* system_state)
210 : UpdaterVariableBase<uint64_t>(name, kVariableModePoll, system_state) {}
211
212 private:
GetValue(TimeDelta,string * errmsg)213 const uint64_t* GetValue(TimeDelta /* timeout */, string* errmsg) override {
214 GetStatusHelper raw(system_state(), errmsg);
215 if (!raw.is_success())
216 return nullptr;
217
218 return new uint64_t(raw.payload_size());
219 }
220
221 DISALLOW_COPY_AND_ASSIGN(PayloadSizeVariable);
222 };
223
224 // A variable reporting the point in time an update last completed in the
225 // current boot cycle.
226 //
227 // TODO(garnold) In general, both the current boottime and wallclock time
228 // readings should come from the time provider and be moderated by the
229 // evaluation context, so that they are uniform throughout the evaluation of a
230 // policy request.
231 class UpdateCompletedTimeVariable : public UpdaterVariableBase<Time> {
232 public:
UpdateCompletedTimeVariable(const string & name,SystemState * system_state)233 UpdateCompletedTimeVariable(const string& name, SystemState* system_state)
234 : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
235
236 private:
GetValue(TimeDelta,string * errmsg)237 const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
238 Time update_boottime;
239 if (!system_state()->update_attempter()->GetBootTimeAtUpdate(
240 &update_boottime)) {
241 if (errmsg)
242 *errmsg = "Update completed time could not be read";
243 return nullptr;
244 }
245
246 chromeos_update_engine::ClockInterface* clock = system_state()->clock();
247 Time curr_boottime = clock->GetBootTime();
248 if (curr_boottime < update_boottime) {
249 if (errmsg)
250 *errmsg = "Update completed time more recent than current time";
251 return nullptr;
252 }
253 TimeDelta duration_since_update = curr_boottime - update_boottime;
254 return new Time(clock->GetWallclockTime() - duration_since_update);
255 }
256
257 DISALLOW_COPY_AND_ASSIGN(UpdateCompletedTimeVariable);
258 };
259
260 // Variables reporting the current image channel.
261 class CurrChannelVariable : public UpdaterVariableBase<string> {
262 public:
CurrChannelVariable(const string & name,SystemState * system_state)263 CurrChannelVariable(const string& name, SystemState* system_state)
264 : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
265
266 private:
GetValue(TimeDelta,string * errmsg)267 const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
268 OmahaRequestParams* request_params = system_state()->request_params();
269 string channel = request_params->current_channel();
270 if (channel.empty()) {
271 if (errmsg)
272 *errmsg = "No current channel";
273 return nullptr;
274 }
275 return new string(channel);
276 }
277
278 DISALLOW_COPY_AND_ASSIGN(CurrChannelVariable);
279 };
280
281 // Variables reporting the new image channel.
282 class NewChannelVariable : public UpdaterVariableBase<string> {
283 public:
NewChannelVariable(const string & name,SystemState * system_state)284 NewChannelVariable(const string& name, SystemState* system_state)
285 : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
286
287 private:
GetValue(TimeDelta,string * errmsg)288 const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
289 OmahaRequestParams* request_params = system_state()->request_params();
290 string channel = request_params->target_channel();
291 if (channel.empty()) {
292 if (errmsg)
293 *errmsg = "No new channel";
294 return nullptr;
295 }
296 return new string(channel);
297 }
298
299 DISALLOW_COPY_AND_ASSIGN(NewChannelVariable);
300 };
301
302 // A variable class for reading Boolean prefs values.
303 class BooleanPrefVariable
304 : public AsyncCopyVariable<bool>,
305 public chromeos_update_engine::PrefsInterface::ObserverInterface {
306 public:
BooleanPrefVariable(const string & name,chromeos_update_engine::PrefsInterface * prefs,const char * key,bool default_val)307 BooleanPrefVariable(const string& name,
308 chromeos_update_engine::PrefsInterface* prefs,
309 const char* key,
310 bool default_val)
311 : AsyncCopyVariable<bool>(name),
312 prefs_(prefs),
313 key_(key),
314 default_val_(default_val) {
315 prefs->AddObserver(key, this);
316 OnPrefSet(key);
317 }
~BooleanPrefVariable()318 ~BooleanPrefVariable() { prefs_->RemoveObserver(key_, this); }
319
320 private:
321 // Reads the actual value from the Prefs instance and updates the Variable
322 // value.
OnPrefSet(const string & key)323 void OnPrefSet(const string& key) override {
324 bool result = default_val_;
325 if (prefs_ && prefs_->Exists(key_) && !prefs_->GetBoolean(key_, &result))
326 result = default_val_;
327 // AsyncCopyVariable will take care of values that didn't change.
328 SetValue(result);
329 }
330
OnPrefDeleted(const string & key)331 void OnPrefDeleted(const string& key) override { SetValue(default_val_); }
332
333 chromeos_update_engine::PrefsInterface* prefs_;
334
335 // The Boolean preference key and default value.
336 const char* const key_;
337 const bool default_val_;
338
339 DISALLOW_COPY_AND_ASSIGN(BooleanPrefVariable);
340 };
341
342 // A variable returning the number of consecutive failed update checks.
343 class ConsecutiveFailedUpdateChecksVariable
344 : public UpdaterVariableBase<unsigned int> {
345 public:
ConsecutiveFailedUpdateChecksVariable(const string & name,SystemState * system_state)346 ConsecutiveFailedUpdateChecksVariable(const string& name,
347 SystemState* system_state)
348 : UpdaterVariableBase<unsigned int>(
349 name, kVariableModePoll, system_state) {}
350
351 private:
GetValue(TimeDelta,string *)352 const unsigned int* GetValue(TimeDelta /* timeout */,
353 string* /* errmsg */) override {
354 return new unsigned int(
355 system_state()->update_attempter()->consecutive_failed_update_checks());
356 }
357
358 DISALLOW_COPY_AND_ASSIGN(ConsecutiveFailedUpdateChecksVariable);
359 };
360
361 // A variable returning the server-dictated poll interval.
362 class ServerDictatedPollIntervalVariable
363 : public UpdaterVariableBase<unsigned int> {
364 public:
ServerDictatedPollIntervalVariable(const string & name,SystemState * system_state)365 ServerDictatedPollIntervalVariable(const string& name,
366 SystemState* system_state)
367 : UpdaterVariableBase<unsigned int>(
368 name, kVariableModePoll, system_state) {}
369
370 private:
GetValue(TimeDelta,string *)371 const unsigned int* GetValue(TimeDelta /* timeout */,
372 string* /* errmsg */) override {
373 return new unsigned int(
374 system_state()->update_attempter()->server_dictated_poll_interval());
375 }
376
377 DISALLOW_COPY_AND_ASSIGN(ServerDictatedPollIntervalVariable);
378 };
379
380 // An async variable that tracks changes to forced update requests.
381 class ForcedUpdateRequestedVariable
382 : public UpdaterVariableBase<UpdateRequestStatus> {
383 public:
ForcedUpdateRequestedVariable(const string & name,SystemState * system_state)384 ForcedUpdateRequestedVariable(const string& name, SystemState* system_state)
385 : UpdaterVariableBase<UpdateRequestStatus>::UpdaterVariableBase(
386 name, kVariableModeAsync, system_state) {
387 system_state->update_attempter()->set_forced_update_pending_callback(
388 new base::Callback<void(bool, bool)>( // NOLINT(readability/function)
389 base::Bind(&ForcedUpdateRequestedVariable::Reset,
390 base::Unretained(this))));
391 }
392
393 private:
GetValue(TimeDelta,string *)394 const UpdateRequestStatus* GetValue(TimeDelta /* timeout */,
395 string* /* errmsg */) override {
396 return new UpdateRequestStatus(update_request_status_);
397 }
398
Reset(bool forced_update_requested,bool interactive)399 void Reset(bool forced_update_requested, bool interactive) {
400 UpdateRequestStatus new_value = UpdateRequestStatus::kNone;
401 if (forced_update_requested)
402 new_value = (interactive ? UpdateRequestStatus::kInteractive
403 : UpdateRequestStatus::kPeriodic);
404 if (update_request_status_ != new_value) {
405 update_request_status_ = new_value;
406 NotifyValueChanged();
407 }
408 }
409
410 UpdateRequestStatus update_request_status_ = UpdateRequestStatus::kNone;
411
412 DISALLOW_COPY_AND_ASSIGN(ForcedUpdateRequestedVariable);
413 };
414
415 // A variable returning the current update restrictions that are in effect.
416 class UpdateRestrictionsVariable
417 : public UpdaterVariableBase<UpdateRestrictions> {
418 public:
UpdateRestrictionsVariable(const string & name,SystemState * system_state)419 UpdateRestrictionsVariable(const string& name, SystemState* system_state)
420 : UpdaterVariableBase<UpdateRestrictions>(
421 name, kVariableModePoll, system_state) {}
422
423 private:
GetValue(TimeDelta,string *)424 const UpdateRestrictions* GetValue(TimeDelta /* timeout */,
425 string* /* errmsg */) override {
426 UpdateAttemptFlags attempt_flags =
427 system_state()->update_attempter()->GetCurrentUpdateAttemptFlags();
428 UpdateRestrictions restriction_flags = UpdateRestrictions::kNone;
429 // Don't blindly copy the whole value, test and set bits that should
430 // transfer from one set of flags to the other.
431 if (attempt_flags & UpdateAttemptFlags::kFlagRestrictDownload) {
432 restriction_flags = static_cast<UpdateRestrictions>(
433 restriction_flags | UpdateRestrictions::kRestrictDownloading);
434 }
435
436 return new UpdateRestrictions(restriction_flags);
437 }
438
439 DISALLOW_COPY_AND_ASSIGN(UpdateRestrictionsVariable);
440 };
441
442 // RealUpdaterProvider methods.
443
RealUpdaterProvider(SystemState * system_state)444 RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
445 : system_state_(system_state),
446 var_updater_started_time_("updater_started_time",
447 system_state->clock()->GetWallclockTime()),
448 var_last_checked_time_(
449 new LastCheckedTimeVariable("last_checked_time", system_state_)),
450 var_update_completed_time_(new UpdateCompletedTimeVariable(
451 "update_completed_time", system_state_)),
452 var_progress_(new ProgressVariable("progress", system_state_)),
453 var_stage_(new StageVariable("stage", system_state_)),
454 var_new_version_(new NewVersionVariable("new_version", system_state_)),
455 var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
456 var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
457 var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
458 var_p2p_enabled_(
459 new BooleanPrefVariable("p2p_enabled",
460 system_state_->prefs(),
461 chromeos_update_engine::kPrefsP2PEnabled,
462 false)),
463 var_cellular_enabled_(new BooleanPrefVariable(
464 "cellular_enabled",
465 system_state_->prefs(),
466 chromeos_update_engine::kPrefsUpdateOverCellularPermission,
467 false)),
468 var_consecutive_failed_update_checks_(
469 new ConsecutiveFailedUpdateChecksVariable(
470 "consecutive_failed_update_checks", system_state_)),
471 var_server_dictated_poll_interval_(new ServerDictatedPollIntervalVariable(
472 "server_dictated_poll_interval", system_state_)),
473 var_forced_update_requested_(new ForcedUpdateRequestedVariable(
474 "forced_update_requested", system_state_)),
475 var_update_restrictions_(new UpdateRestrictionsVariable(
476 "update_restrictions", system_state_)) {}
477 } // namespace chromeos_update_manager
478