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