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