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