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