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/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:
     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.
     57   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:
     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 
     74   inline bool is_success() { return is_success_; }
     75   inline int64_t last_checked_time() {
     76     return update_engine_status_.last_checked_time;
     77   }
     78   inline double progress() { return update_engine_status_.progress; }
     79   inline const string update_status() {
     80     return chromeos_update_engine::UpdateStatusToString(
     81         update_engine_status_.status);
     82   }
     83   inline const string& new_version() {
     84     return update_engine_status_.new_version;
     85   }
     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:
     98   LastCheckedTimeVariable(const string& name, SystemState* system_state)
     99       : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
    100 
    101  private:
    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:
    117   ProgressVariable(const string& name, SystemState* system_state)
    118       : UpdaterVariableBase<double>(name, kVariableModePoll, system_state) {}
    119 
    120  private:
    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:
    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 
    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:
    192   NewVersionVariable(const string& name, SystemState* system_state)
    193       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
    194 
    195  private:
    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:
    210   PayloadSizeVariable(const string& name, SystemState* system_state)
    211       : UpdaterVariableBase<uint64_t>(name, kVariableModePoll, system_state) {}
    212 
    213  private:
    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:
    234   UpdateCompletedTimeVariable(const string& name, SystemState* system_state)
    235       : UpdaterVariableBase<Time>(name, kVariableModePoll, system_state) {}
    236 
    237  private:
    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:
    264   CurrChannelVariable(const string& name, SystemState* system_state)
    265       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
    266 
    267  private:
    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:
    285   NewChannelVariable(const string& name, SystemState* system_state)
    286       : UpdaterVariableBase<string>(name, kVariableModePoll, system_state) {}
    287 
    288  private:
    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:
    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   }
    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.
    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 
    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:
    351   ConsecutiveFailedUpdateChecksVariable(const string& name,
    352                                         SystemState* system_state)
    353       : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
    354                                           system_state) {}
    355 
    356  private:
    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:
    370   ServerDictatedPollIntervalVariable(const string& name,
    371                                      SystemState* system_state)
    372       : UpdaterVariableBase<unsigned int>(name, kVariableModePoll,
    373                                           system_state) {}
    374 
    375  private:
    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:
    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:
    399   const UpdateRequestStatus* GetValue(TimeDelta /* timeout */,
    400                                       string* /* errmsg */) override {
    401     return new UpdateRequestStatus(update_request_status_);
    402   }
    403 
    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:
    424   UpdateRestrictionsVariable(const string& name, SystemState* system_state)
    425       : UpdaterVariableBase<UpdateRestrictions>(
    426             name, kVariableModePoll, system_state) {}
    427 
    428  private:
    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 
    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