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/common/clock_interface.h"
29 #include "update_engine/common/prefs.h"
30 #include "update_engine/omaha_request_params.h"
31 #include "update_engine/update_attempter.h"
32 
33 using base::StringPrintf;
34 using base::Time;
35 using base::TimeDelta;
36 using chromeos_update_engine::OmahaRequestParams;
37 using chromeos_update_engine::SystemState;
38 using std::string;
39 
40 namespace chromeos_update_manager {
41 
42 // A templated base class for all update related variables. Provides uniform
43 // construction and a system state handle.
44 template<typename T>
45 class UpdaterVariableBase : public Variable<T> {
46  public:
UpdaterVariableBase(const string & name,VariableMode mode,SystemState * system_state)47   UpdaterVariableBase(const string& name, VariableMode mode,
48                       SystemState* system_state)
49       : Variable<T>(name, mode), system_state_(system_state) {}
50 
51  protected:
52   // The system state used for pulling information from the updater.
system_state() const53   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.
60 class GetStatusHelper {
61  public:
GetStatusHelper(SystemState * system_state,string * errmsg)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 
is_success()70   inline bool is_success() { return is_success_; }
last_checked_time()71   inline int64_t last_checked_time() { return last_checked_time_; }
progress()72   inline double progress() { return progress_; }
update_status()73   inline const string& update_status() { return update_status_; }
new_version()74   inline const string& new_version() { return new_version_; }
payload_size()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.
87 class LastCheckedTimeVariable : public UpdaterVariableBase<Time> {
88  public:
LastCheckedTimeVariable(const string & name,SystemState * system_state)89   LastCheckedTimeVariable(const string& name, SystemState* system_state)
90       : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
91 
92  private:
GetValue(TimeDelta,string * errmsg)93   const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
94     GetStatusHelper raw(system_state(), errmsg);
95     if (!raw.is_success())
96       return nullptr;
97 
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.
106 class ProgressVariable : public UpdaterVariableBase<double> {
107  public:
ProgressVariable(const string & name,SystemState * system_state)108   ProgressVariable(const string& name, SystemState* system_state)
109       : UpdaterVariableBase<double>(name, kVariableModePoll, system_state) {}
110 
111  private:
GetValue(TimeDelta,string * errmsg)112   const double* GetValue(TimeDelta /* timeout */, string* errmsg) override {
113     GetStatusHelper raw(system_state(), errmsg);
114     if (!raw.is_success())
115       return nullptr;
116 
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       }
122       return nullptr;
123     }
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.
132 class StageVariable : public UpdaterVariableBase<Stage> {
133  public:
StageVariable(const string & name,SystemState * system_state)134   StageVariable(const string& name, SystemState* system_state)
135       : UpdaterVariableBase<Stage>(name, kVariableModePoll, system_state) {}
136 
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.
145   const Stage* GetValue(TimeDelta /* timeout */, string* errmsg) override;
146 
147   DISALLOW_COPY_AND_ASSIGN(StageVariable);
148 };
149 
150 const 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},
158   {  // NOLINT(whitespace/braces)
159     update_engine::kUpdateStatusReportingErrorEvent,
160     Stage::kReportingErrorEvent
161   },
162   {update_engine::kUpdateStatusAttemptingRollback, Stage::kAttemptingRollback},
163 };
164 
GetValue(TimeDelta,string * errmsg)165 const Stage* StageVariable::GetValue(TimeDelta /* timeout */,
166                                      string* errmsg) {
167   GetStatusHelper raw(system_state(), errmsg);
168   if (!raw.is_success())
169     return nullptr;
170 
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();
177   return nullptr;
178 }
179 
180 // A variable reporting the version number that an update is updating to.
181 class NewVersionVariable : public UpdaterVariableBase<string> {
182  public:
NewVersionVariable(const string & name,SystemState * system_state)183   NewVersionVariable(const string& name, SystemState* system_state)
184       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
185 
186  private:
GetValue(TimeDelta,string * errmsg)187   const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
188     GetStatusHelper raw(system_state(), errmsg);
189     if (!raw.is_success())
190       return nullptr;
191 
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.
199 class PayloadSizeVariable : public UpdaterVariableBase<int64_t> {
200  public:
PayloadSizeVariable(const string & name,SystemState * system_state)201   PayloadSizeVariable(const string& name, SystemState* system_state)
202       : UpdaterVariableBase<int64_t>(name, kVariableModePoll, system_state) {}
203 
204  private:
GetValue(TimeDelta,string * errmsg)205   const int64_t* GetValue(TimeDelta /* timeout */, string* errmsg) override {
206     GetStatusHelper raw(system_state(), errmsg);
207     if (!raw.is_success())
208       return nullptr;
209 
210     if (raw.payload_size() < 0) {
211       if (errmsg)
212         *errmsg = string("Invalid payload size: %" PRId64, raw.payload_size());
213       return nullptr;
214     }
215 
216     return new int64_t(raw.payload_size());
217   }
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.
229 class UpdateCompletedTimeVariable : public UpdaterVariableBase<Time> {
230  public:
UpdateCompletedTimeVariable(const string & name,SystemState * system_state)231   UpdateCompletedTimeVariable(const string& name, SystemState* system_state)
232       : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
233 
234  private:
GetValue(TimeDelta,string * errmsg)235   const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override {
236     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";
241       return nullptr;
242     }
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";
249       return nullptr;
250     }
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.
259 class CurrChannelVariable : public UpdaterVariableBase<string> {
260  public:
CurrChannelVariable(const string & name,SystemState * system_state)261   CurrChannelVariable(const string& name, SystemState* system_state)
262       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
263 
264  private:
GetValue(TimeDelta,string * errmsg)265   const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
266     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";
271       return nullptr;
272     }
273     return new string(channel);
274   }
275 
276   DISALLOW_COPY_AND_ASSIGN(CurrChannelVariable);
277 };
278 
279 // Variables reporting the new image channel.
280 class NewChannelVariable : public UpdaterVariableBase<string> {
281  public:
NewChannelVariable(const string & name,SystemState * system_state)282   NewChannelVariable(const string& name, SystemState* system_state)
283       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
284 
285  private:
GetValue(TimeDelta,string * errmsg)286   const string* GetValue(TimeDelta /* timeout */, string* errmsg) override {
287     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";
292       return nullptr;
293     }
294     return new string(channel);
295   }
296 
297   DISALLOW_COPY_AND_ASSIGN(NewChannelVariable);
298 };
299 
300 // A variable class for reading Boolean prefs values.
301 class BooleanPrefVariable
302     : public AsyncCopyVariable<bool>,
303       public chromeos_update_engine::PrefsInterface::ObserverInterface {
304  public:
BooleanPrefVariable(const string & name,chromeos_update_engine::PrefsInterface * prefs,const char * key,bool default_val)305   BooleanPrefVariable(const string& name,
306                       chromeos_update_engine::PrefsInterface* prefs,
307                       const char* key,
308                       bool default_val)
309       : AsyncCopyVariable<bool>(name),
310         prefs_(prefs),
311         key_(key),
312         default_val_(default_val) {
313     prefs->AddObserver(key, this);
314     OnPrefSet(key);
315   }
~BooleanPrefVariable()316   ~BooleanPrefVariable() {
317     prefs_->RemoveObserver(key_, this);
318   }
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 {
332     SetValue(default_val_);
333   }
334 
335   chromeos_update_engine::PrefsInterface* prefs_;
336 
337   // The Boolean preference key and default value.
338   const char* const key_;
339   const bool default_val_;
340 
341   DISALLOW_COPY_AND_ASSIGN(BooleanPrefVariable);
342 };
343 
344 // A variable returning the number of consecutive failed update checks.
345 class ConsecutiveFailedUpdateChecksVariable
346     : public UpdaterVariableBase<unsigned int> {
347  public:
ConsecutiveFailedUpdateChecksVariable(const string & name,SystemState * system_state)348   ConsecutiveFailedUpdateChecksVariable(const string& name,
349                                         SystemState* system_state)
350       : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
351                                           system_state) {}
352 
353  private:
GetValue(TimeDelta,string *)354   const unsigned int* GetValue(TimeDelta /* timeout */,
355                                string* /* errmsg */) override {
356     return new unsigned int(
357         system_state()->update_attempter()->consecutive_failed_update_checks());
358   }
359 
360   DISALLOW_COPY_AND_ASSIGN(ConsecutiveFailedUpdateChecksVariable);
361 };
362 
363 // A variable returning the server-dictated poll interval.
364 class ServerDictatedPollIntervalVariable
365     : public UpdaterVariableBase<unsigned int> {
366  public:
ServerDictatedPollIntervalVariable(const string & name,SystemState * system_state)367   ServerDictatedPollIntervalVariable(const string& name,
368                                      SystemState* system_state)
369       : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
370                                           system_state) {}
371 
372  private:
GetValue(TimeDelta,string *)373   const unsigned int* GetValue(TimeDelta /* timeout */,
374                                string* /* errmsg */) override {
375     return new unsigned int(
376         system_state()->update_attempter()->server_dictated_poll_interval());
377   }
378 
379   DISALLOW_COPY_AND_ASSIGN(ServerDictatedPollIntervalVariable);
380 };
381 
382 // An async variable that tracks changes to forced update requests.
383 class ForcedUpdateRequestedVariable
384     : public UpdaterVariableBase<UpdateRequestStatus> {
385  public:
ForcedUpdateRequestedVariable(const string & name,SystemState * system_state)386   ForcedUpdateRequestedVariable(const string& name, SystemState* system_state)
387       : UpdaterVariableBase<UpdateRequestStatus>::UpdaterVariableBase(
388           name, kVariableModeAsync, system_state) {
389     system_state->update_attempter()->set_forced_update_pending_callback(
390         new base::Callback<void(bool, bool)>(  // NOLINT(readability/function)
391             base::Bind(&ForcedUpdateRequestedVariable::Reset,
392                        base::Unretained(this))));
393   }
394 
395  private:
GetValue(TimeDelta,string *)396   const UpdateRequestStatus* GetValue(TimeDelta /* timeout */,
397                                       string* /* errmsg */) override {
398     return new UpdateRequestStatus(update_request_status_);
399   }
400 
Reset(bool forced_update_requested,bool is_interactive)401   void Reset(bool forced_update_requested, bool is_interactive) {
402     UpdateRequestStatus new_value = UpdateRequestStatus::kNone;
403     if (forced_update_requested)
404       new_value = (is_interactive ? UpdateRequestStatus::kInteractive :
405                    UpdateRequestStatus::kPeriodic);
406     if (update_request_status_ != new_value) {
407       update_request_status_ = new_value;
408       NotifyValueChanged();
409     }
410   }
411 
412   UpdateRequestStatus update_request_status_ = UpdateRequestStatus::kNone;
413 
414   DISALLOW_COPY_AND_ASSIGN(ForcedUpdateRequestedVariable);
415 };
416 
417 // RealUpdaterProvider methods.
418 
RealUpdaterProvider(SystemState * system_state)419 RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
420   : system_state_(system_state),
421     var_updater_started_time_("updater_started_time",
422                               system_state->clock()->GetWallclockTime()),
423     var_last_checked_time_(
424         new LastCheckedTimeVariable("last_checked_time", system_state_)),
425     var_update_completed_time_(
426         new UpdateCompletedTimeVariable("update_completed_time",
427                                         system_state_)),
428     var_progress_(new ProgressVariable("progress", system_state_)),
429     var_stage_(new StageVariable("stage", system_state_)),
430     var_new_version_(new NewVersionVariable("new_version", system_state_)),
431     var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
432     var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
433     var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
434     var_p2p_enabled_(
435         new BooleanPrefVariable("p2p_enabled", system_state_->prefs(),
436                                 chromeos_update_engine::kPrefsP2PEnabled,
437                                 false)),
438     var_cellular_enabled_(
439         new BooleanPrefVariable(
440             "cellular_enabled", system_state_->prefs(),
441             chromeos_update_engine::kPrefsUpdateOverCellularPermission,
442             false)),
443     var_consecutive_failed_update_checks_(
444         new ConsecutiveFailedUpdateChecksVariable(
445             "consecutive_failed_update_checks", system_state_)),
446     var_server_dictated_poll_interval_(
447         new ServerDictatedPollIntervalVariable(
448             "server_dictated_poll_interval", system_state_)),
449     var_forced_update_requested_(
450         new ForcedUpdateRequestedVariable(
451             "forced_update_requested", system_state_)) {}
452 
453 }  // namespace chromeos_update_manager
454