Home | History | Annotate | Download | only in update_manager
      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:
     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.
     53   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:
     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 
     70   inline bool is_success() { return is_success_; }
     71   inline int64_t last_checked_time() { return last_checked_time_; }
     72   inline double progress() { return progress_; }
     73   inline const string& update_status() { return update_status_; }
     74   inline const string& new_version() { return new_version_; }
     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:
     89   LastCheckedTimeVariable(const string& name, SystemState* system_state)
     90       : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
     91 
     92  private:
     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:
    108   ProgressVariable(const string& name, SystemState* system_state)
    109       : UpdaterVariableBase<double>(name, kVariableModePoll, system_state) {}
    110 
    111  private:
    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:
    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 
    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:
    183   NewVersionVariable(const string& name, SystemState* system_state)
    184       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
    185 
    186  private:
    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:
    201   PayloadSizeVariable(const string& name, SystemState* system_state)
    202       : UpdaterVariableBase<int64_t>(name, kVariableModePoll, system_state) {}
    203 
    204  private:
    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:
    231   UpdateCompletedTimeVariable(const string& name, SystemState* system_state)
    232       : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
    233 
    234  private:
    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:
    261   CurrChannelVariable(const string& name, SystemState* system_state)
    262       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
    263 
    264  private:
    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:
    282   NewChannelVariable(const string& name, SystemState* system_state)
    283       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
    284 
    285  private:
    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:
    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   }
    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.
    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 
    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:
    348   ConsecutiveFailedUpdateChecksVariable(const string& name,
    349                                         SystemState* system_state)
    350       : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
    351                                           system_state) {}
    352 
    353  private:
    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:
    367   ServerDictatedPollIntervalVariable(const string& name,
    368                                      SystemState* system_state)
    369       : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
    370                                           system_state) {}
    371 
    372  private:
    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:
    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:
    396   const UpdateRequestStatus* GetValue(TimeDelta /* timeout */,
    397                                       string* /* errmsg */) override {
    398     return new UpdateRequestStatus(update_request_status_);
    399   }
    400 
    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 
    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