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