update_attempter.cc revision aa18e1641879f2df5993c2b02eb6f50d4443a649
1// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "update_engine/update_attempter.h" 6 7#include <string> 8#include <tr1/memory> 9#include <vector> 10 11#include <base/file_util.h> 12#include <base/rand_util.h> 13#include <glib.h> 14#include <metrics/metrics_library.h> 15#include <policy/libpolicy.h> 16#include <policy/device_policy.h> 17 18#include "update_engine/certificate_checker.h" 19#include "update_engine/constants.h" 20#include "update_engine/dbus_service.h" 21#include "update_engine/download_action.h" 22#include "update_engine/filesystem_copier_action.h" 23#include "update_engine/gpio_handler.h" 24#include "update_engine/libcurl_http_fetcher.h" 25#include "update_engine/multi_range_http_fetcher.h" 26#include "update_engine/omaha_request_action.h" 27#include "update_engine/omaha_request_params.h" 28#include "update_engine/omaha_response_handler_action.h" 29#include "update_engine/payload_state_interface.h" 30#include "update_engine/postinstall_runner_action.h" 31#include "update_engine/prefs_interface.h" 32#include "update_engine/subprocess.h" 33#include "update_engine/system_state.h" 34#include "update_engine/update_check_scheduler.h" 35 36using base::TimeDelta; 37using base::TimeTicks; 38using google::protobuf::NewPermanentCallback; 39using std::make_pair; 40using std::tr1::shared_ptr; 41using std::set; 42using std::string; 43using std::vector; 44 45namespace chromeos_update_engine { 46 47const int UpdateAttempter::kMaxDeltaUpdateFailures = 3; 48 49// Private test server URL w/ custom port number. 50// TODO(garnold) This is a temporary hack to allow us to test the closed loop 51// automated update testing. To be replaced with an hard-coded local IP address. 52const char* const UpdateAttempter::kTestUpdateUrl( 53 "http://garnold.mtv.corp.google.com:8080/update"); 54 55const char* kUpdateCompletedMarker = 56 "/var/run/update_engine_autoupdate_completed"; 57 58namespace { 59const int kMaxConsecutiveObeyProxyRequests = 20; 60} // namespace {} 61 62const char* UpdateStatusToString(UpdateStatus status) { 63 switch (status) { 64 case UPDATE_STATUS_IDLE: 65 return "UPDATE_STATUS_IDLE"; 66 case UPDATE_STATUS_CHECKING_FOR_UPDATE: 67 return "UPDATE_STATUS_CHECKING_FOR_UPDATE"; 68 case UPDATE_STATUS_UPDATE_AVAILABLE: 69 return "UPDATE_STATUS_UPDATE_AVAILABLE"; 70 case UPDATE_STATUS_DOWNLOADING: 71 return "UPDATE_STATUS_DOWNLOADING"; 72 case UPDATE_STATUS_VERIFYING: 73 return "UPDATE_STATUS_VERIFYING"; 74 case UPDATE_STATUS_FINALIZING: 75 return "UPDATE_STATUS_FINALIZING"; 76 case UPDATE_STATUS_UPDATED_NEED_REBOOT: 77 return "UPDATE_STATUS_UPDATED_NEED_REBOOT"; 78 case UPDATE_STATUS_REPORTING_ERROR_EVENT: 79 return "UPDATE_STATUS_REPORTING_ERROR_EVENT"; 80 case UPDATE_STATUS_ATTEMPTING_ROLLBACK: 81 return "UPDATE_STATUS_ATTEMPTING_ROLLBACK"; 82 default: 83 return "unknown status"; 84 } 85} 86 87// Turns a generic kErrorCodeError to a generic error code specific 88// to |action| (e.g., kErrorCodeFilesystemCopierError). If |code| is 89// not kErrorCodeError, or the action is not matched, returns |code| 90// unchanged. 91ErrorCode GetErrorCodeForAction(AbstractAction* action, 92 ErrorCode code) { 93 if (code != kErrorCodeError) 94 return code; 95 96 const string type = action->Type(); 97 if (type == OmahaRequestAction::StaticType()) 98 return kErrorCodeOmahaRequestError; 99 if (type == OmahaResponseHandlerAction::StaticType()) 100 return kErrorCodeOmahaResponseHandlerError; 101 if (type == FilesystemCopierAction::StaticType()) 102 return kErrorCodeFilesystemCopierError; 103 if (type == PostinstallRunnerAction::StaticType()) 104 return kErrorCodePostinstallRunnerError; 105 106 return code; 107} 108 109UpdateAttempter::UpdateAttempter(SystemState* system_state, 110 DbusGlibInterface* dbus_iface) 111 : processor_(new ActionProcessor()), 112 system_state_(system_state), 113 dbus_service_(NULL), 114 update_check_scheduler_(NULL), 115 fake_update_success_(false), 116 http_response_code_(0), 117 shares_(utils::kCpuSharesNormal), 118 manage_shares_source_(NULL), 119 download_active_(false), 120 status_(UPDATE_STATUS_IDLE), 121 download_progress_(0.0), 122 last_checked_time_(0), 123 new_version_("0.0.0.0"), 124 new_payload_size_(0), 125 proxy_manual_checks_(0), 126 obeying_proxies_(true), 127 chrome_proxy_resolver_(dbus_iface), 128 updated_boot_flags_(false), 129 update_boot_flags_running_(false), 130 start_action_processor_(false), 131 policy_provider_(NULL), 132 is_using_test_url_(false), 133 is_test_mode_(false), 134 is_test_update_attempted_(false) { 135 prefs_ = system_state->prefs(); 136 omaha_request_params_ = system_state->request_params(); 137 if (utils::FileExists(kUpdateCompletedMarker)) 138 status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT; 139} 140 141UpdateAttempter::~UpdateAttempter() { 142 CleanupCpuSharesManagement(); 143} 144 145void UpdateAttempter::Update(const string& app_version, 146 const string& omaha_url, 147 bool obey_proxies, 148 bool interactive, 149 bool is_test_mode) { 150 chrome_proxy_resolver_.Init(); 151 fake_update_success_ = false; 152 if (status_ == UPDATE_STATUS_UPDATED_NEED_REBOOT) { 153 // Although we have applied an update, we still want to ping Omaha 154 // to ensure the number of active statistics is accurate. 155 LOG(INFO) << "Not updating b/c we already updated and we're waiting for " 156 << "reboot, we'll ping Omaha instead"; 157 PingOmaha(); 158 return; 159 } 160 if (status_ != UPDATE_STATUS_IDLE) { 161 // Update in progress. Do nothing 162 return; 163 } 164 165 if (!CalculateUpdateParams(app_version, 166 omaha_url, 167 obey_proxies, 168 interactive, 169 is_test_mode)) { 170 return; 171 } 172 173 BuildUpdateActions(interactive); 174 175 SetStatusAndNotify(UPDATE_STATUS_CHECKING_FOR_UPDATE, 176 kUpdateNoticeUnspecified); 177 178 // Just in case we didn't update boot flags yet, make sure they're updated 179 // before any update processing starts. 180 start_action_processor_ = true; 181 UpdateBootFlags(); 182} 183 184void UpdateAttempter::RefreshDevicePolicy() { 185 // Lazy initialize the policy provider, or reload the latest policy data. 186 if (!policy_provider_.get()) 187 policy_provider_.reset(new policy::PolicyProvider()); 188 policy_provider_->Reload(); 189 190 const policy::DevicePolicy* device_policy = NULL; 191 if (policy_provider_->device_policy_is_loaded()) 192 device_policy = &policy_provider_->GetDevicePolicy(); 193 194 if (device_policy) 195 LOG(INFO) << "Device policies/settings present"; 196 else 197 LOG(INFO) << "No device policies/settings present."; 198 199 system_state_->set_device_policy(device_policy); 200} 201 202bool UpdateAttempter::CalculateUpdateParams(const string& app_version, 203 const string& omaha_url, 204 bool obey_proxies, 205 bool interactive, 206 bool is_test_mode) { 207 http_response_code_ = 0; 208 209 // Set the test mode flag for the current update attempt. 210 is_test_mode_ = is_test_mode; 211 RefreshDevicePolicy(); 212 const policy::DevicePolicy* device_policy = system_state_->device_policy(); 213 if (device_policy) { 214 bool update_disabled = false; 215 if (device_policy->GetUpdateDisabled(&update_disabled)) 216 omaha_request_params_->set_update_disabled(update_disabled); 217 218 string target_version_prefix; 219 if (device_policy->GetTargetVersionPrefix(&target_version_prefix)) 220 omaha_request_params_->set_target_version_prefix(target_version_prefix); 221 222 set<string> allowed_types; 223 string allowed_types_str; 224 if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) { 225 set<string>::const_iterator iter; 226 for (iter = allowed_types.begin(); iter != allowed_types.end(); ++iter) 227 allowed_types_str += *iter + " "; 228 } 229 230 LOG(INFO) << "Networks over which updates are allowed per policy : " 231 << (allowed_types_str.empty() ? "all" : allowed_types_str); 232 } 233 234 CalculateScatteringParams(interactive); 235 236 // Determine whether an alternative test address should be used. 237 string omaha_url_to_use = omaha_url; 238 if ((is_using_test_url_ = (omaha_url_to_use.empty() && is_test_mode_))) { 239 omaha_url_to_use = kTestUpdateUrl; 240 LOG(INFO) << "using alternative server address: " << omaha_url_to_use; 241 } 242 243 if (!omaha_request_params_->Init(app_version, 244 omaha_url_to_use, 245 interactive)) { 246 LOG(ERROR) << "Unable to initialize Omaha request params."; 247 return false; 248 } 249 250 // Set the target channel iff ReleaseChannelDelegated policy is set to 251 // false and a non-empty ReleaseChannel policy is present. If delegated 252 // is true, we'll ignore ReleaseChannel policy value. 253 if (device_policy) { 254 bool delegated = false; 255 if (device_policy->GetReleaseChannelDelegated(&delegated) && delegated) { 256 LOG(INFO) << "Channel settings are delegated to user by policy. " 257 "Ignoring ReleaseChannel policy value"; 258 } 259 else { 260 LOG(INFO) << "Channel settings are not delegated to the user by policy"; 261 string target_channel; 262 if (device_policy->GetReleaseChannel(&target_channel) && 263 !target_channel.empty()) { 264 // Pass in false for powerwash_allowed until we add it to the policy 265 // protobuf. 266 LOG(INFO) << "Setting target channel from ReleaseChannel policy value"; 267 omaha_request_params_->SetTargetChannel(target_channel, false); 268 269 // Since this is the beginning of a new attempt, update the download 270 // channel. The download channel won't be updated until the next 271 // attempt, even if target channel changes meanwhile, so that how we'll 272 // know if we should cancel the current download attempt if there's 273 // such a change in target channel. 274 omaha_request_params_->UpdateDownloadChannel(); 275 } else { 276 LOG(INFO) << "No ReleaseChannel specified in policy"; 277 } 278 } 279 } 280 281 LOG(INFO) << "update_disabled = " 282 << utils::ToString(omaha_request_params_->update_disabled()) 283 << ", target_version_prefix = " 284 << omaha_request_params_->target_version_prefix() 285 << ", scatter_factor_in_seconds = " 286 << utils::FormatSecs(scatter_factor_.InSeconds()); 287 288 LOG(INFO) << "Wall Clock Based Wait Enabled = " 289 << omaha_request_params_->wall_clock_based_wait_enabled() 290 << ", Update Check Count Wait Enabled = " 291 << omaha_request_params_->update_check_count_wait_enabled() 292 << ", Waiting Period = " << utils::FormatSecs( 293 omaha_request_params_->waiting_period().InSeconds()); 294 295 obeying_proxies_ = true; 296 if (obey_proxies || proxy_manual_checks_ == 0) { 297 LOG(INFO) << "forced to obey proxies"; 298 // If forced to obey proxies, every 20th request will not use proxies 299 proxy_manual_checks_++; 300 LOG(INFO) << "proxy manual checks: " << proxy_manual_checks_; 301 if (proxy_manual_checks_ >= kMaxConsecutiveObeyProxyRequests) { 302 proxy_manual_checks_ = 0; 303 obeying_proxies_ = false; 304 } 305 } else if (base::RandInt(0, 4) == 0) { 306 obeying_proxies_ = false; 307 } 308 LOG_IF(INFO, !obeying_proxies_) << "To help ensure updates work, this update " 309 "check we are ignoring the proxy settings and using " 310 "direct connections."; 311 312 DisableDeltaUpdateIfNeeded(); 313 return true; 314} 315 316void UpdateAttempter::CalculateScatteringParams(bool interactive) { 317 // Take a copy of the old scatter value before we update it, as 318 // we need to update the waiting period if this value changes. 319 TimeDelta old_scatter_factor = scatter_factor_; 320 const policy::DevicePolicy* device_policy = system_state_->device_policy(); 321 if (device_policy) { 322 int64 new_scatter_factor_in_secs = 0; 323 device_policy->GetScatterFactorInSeconds(&new_scatter_factor_in_secs); 324 if (new_scatter_factor_in_secs < 0) // sanitize input, just in case. 325 new_scatter_factor_in_secs = 0; 326 scatter_factor_ = TimeDelta::FromSeconds(new_scatter_factor_in_secs); 327 } 328 329 bool is_scatter_enabled = false; 330 if (scatter_factor_.InSeconds() == 0) { 331 LOG(INFO) << "Scattering disabled since scatter factor is set to 0"; 332 } else if (interactive) { 333 LOG(INFO) << "Scattering disabled as this is an interactive update check"; 334 } else if (!system_state_->IsOOBEComplete()) { 335 LOG(INFO) << "Scattering disabled since OOBE is not complete yet"; 336 } else { 337 is_scatter_enabled = true; 338 LOG(INFO) << "Scattering is enabled"; 339 } 340 341 if (is_scatter_enabled) { 342 // This means the scattering policy is turned on. 343 // Now check if we need to update the waiting period. The two cases 344 // in which we'd need to update the waiting period are: 345 // 1. First time in process or a scheduled check after a user-initiated one. 346 // (omaha_request_params_->waiting_period will be zero in this case). 347 // 2. Admin has changed the scattering policy value. 348 // (new scattering value will be different from old one in this case). 349 int64 wait_period_in_secs = 0; 350 if (omaha_request_params_->waiting_period().InSeconds() == 0) { 351 // First case. Check if we have a suitable value to set for 352 // the waiting period. 353 if (prefs_->GetInt64(kPrefsWallClockWaitPeriod, &wait_period_in_secs) && 354 wait_period_in_secs > 0 && 355 wait_period_in_secs <= scatter_factor_.InSeconds()) { 356 // This means: 357 // 1. There's a persisted value for the waiting period available. 358 // 2. And that persisted value is still valid. 359 // So, in this case, we should reuse the persisted value instead of 360 // generating a new random value to improve the chances of a good 361 // distribution for scattering. 362 omaha_request_params_->set_waiting_period( 363 TimeDelta::FromSeconds(wait_period_in_secs)); 364 LOG(INFO) << "Using persisted wall-clock waiting period: " << 365 utils::FormatSecs( 366 omaha_request_params_->waiting_period().InSeconds()); 367 } 368 else { 369 // This means there's no persisted value for the waiting period 370 // available or its value is invalid given the new scatter_factor value. 371 // So, we should go ahead and regenerate a new value for the 372 // waiting period. 373 LOG(INFO) << "Persisted value not present or not valid (" 374 << utils::FormatSecs(wait_period_in_secs) 375 << ") for wall-clock waiting period."; 376 GenerateNewWaitingPeriod(); 377 } 378 } else if (scatter_factor_ != old_scatter_factor) { 379 // This means there's already a waiting period value, but we detected 380 // a change in the scattering policy value. So, we should regenerate the 381 // waiting period to make sure it's within the bounds of the new scatter 382 // factor value. 383 GenerateNewWaitingPeriod(); 384 } else { 385 // Neither the first time scattering is enabled nor the scattering value 386 // changed. Nothing to do. 387 LOG(INFO) << "Keeping current wall-clock waiting period: " << 388 utils::FormatSecs( 389 omaha_request_params_->waiting_period().InSeconds()); 390 } 391 392 // The invariant at this point is that omaha_request_params_->waiting_period 393 // is non-zero no matter which path we took above. 394 LOG_IF(ERROR, omaha_request_params_->waiting_period().InSeconds() == 0) 395 << "Waiting Period should NOT be zero at this point!!!"; 396 397 // Since scattering is enabled, wall clock based wait will always be 398 // enabled. 399 omaha_request_params_->set_wall_clock_based_wait_enabled(true); 400 401 // If we don't have any issues in accessing the file system to update 402 // the update check count value, we'll turn that on as well. 403 bool decrement_succeeded = DecrementUpdateCheckCount(); 404 omaha_request_params_->set_update_check_count_wait_enabled( 405 decrement_succeeded); 406 } else { 407 // This means the scattering feature is turned off or disabled for 408 // this particular update check. Make sure to disable 409 // all the knobs and artifacts so that we don't invoke any scattering 410 // related code. 411 omaha_request_params_->set_wall_clock_based_wait_enabled(false); 412 omaha_request_params_->set_update_check_count_wait_enabled(false); 413 omaha_request_params_->set_waiting_period(TimeDelta::FromSeconds(0)); 414 prefs_->Delete(kPrefsWallClockWaitPeriod); 415 prefs_->Delete(kPrefsUpdateCheckCount); 416 // Don't delete the UpdateFirstSeenAt file as we don't want manual checks 417 // that result in no-updates (e.g. due to server side throttling) to 418 // cause update starvation by having the client generate a new 419 // UpdateFirstSeenAt for each scheduled check that follows a manual check. 420 } 421} 422 423void UpdateAttempter::GenerateNewWaitingPeriod() { 424 omaha_request_params_->set_waiting_period(TimeDelta::FromSeconds( 425 base::RandInt(1, scatter_factor_.InSeconds()))); 426 427 LOG(INFO) << "Generated new wall-clock waiting period: " << utils::FormatSecs( 428 omaha_request_params_->waiting_period().InSeconds()); 429 430 // Do a best-effort to persist this in all cases. Even if the persistence 431 // fails, we'll still be able to scatter based on our in-memory value. 432 // The persistence only helps in ensuring a good overall distribution 433 // across multiple devices if they tend to reboot too often. 434 prefs_->SetInt64(kPrefsWallClockWaitPeriod, 435 omaha_request_params_->waiting_period().InSeconds()); 436} 437 438void UpdateAttempter::BuildPostInstallActions( 439 InstallPlanAction* previous_action) { 440 shared_ptr<PostinstallRunnerAction> postinstall_runner_action( 441 new PostinstallRunnerAction()); 442 actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action)); 443 BondActions(previous_action, 444 postinstall_runner_action.get()); 445} 446 447void UpdateAttempter::BuildUpdateActions(bool interactive) { 448 CHECK(!processor_->IsRunning()); 449 processor_->set_delegate(this); 450 451 // Actions: 452 LibcurlHttpFetcher* update_check_fetcher = 453 new LibcurlHttpFetcher(GetProxyResolver(), system_state_, is_test_mode_); 454 // Try harder to connect to the network, esp when not interactive. 455 // See comment in libcurl_http_fetcher.cc. 456 update_check_fetcher->set_no_network_max_retries(interactive ? 1 : 3); 457 update_check_fetcher->set_check_certificate(CertificateChecker::kUpdate); 458 shared_ptr<OmahaRequestAction> update_check_action( 459 new OmahaRequestAction(system_state_, 460 NULL, 461 update_check_fetcher, // passes ownership 462 false)); 463 shared_ptr<OmahaResponseHandlerAction> response_handler_action( 464 new OmahaResponseHandlerAction(system_state_)); 465 shared_ptr<FilesystemCopierAction> filesystem_copier_action( 466 new FilesystemCopierAction(false, false)); 467 shared_ptr<FilesystemCopierAction> kernel_filesystem_copier_action( 468 new FilesystemCopierAction(true, false)); 469 shared_ptr<OmahaRequestAction> download_started_action( 470 new OmahaRequestAction(system_state_, 471 new OmahaEvent( 472 OmahaEvent::kTypeUpdateDownloadStarted), 473 new LibcurlHttpFetcher(GetProxyResolver(), 474 system_state_, 475 is_test_mode_), 476 false)); 477 LibcurlHttpFetcher* download_fetcher = 478 new LibcurlHttpFetcher(GetProxyResolver(), system_state_, is_test_mode_); 479 download_fetcher->set_check_certificate(CertificateChecker::kDownload); 480 shared_ptr<DownloadAction> download_action( 481 new DownloadAction(prefs_, 482 system_state_, 483 new MultiRangeHttpFetcher( 484 download_fetcher))); // passes ownership 485 shared_ptr<OmahaRequestAction> download_finished_action( 486 new OmahaRequestAction(system_state_, 487 new OmahaEvent( 488 OmahaEvent::kTypeUpdateDownloadFinished), 489 new LibcurlHttpFetcher(GetProxyResolver(), 490 system_state_, 491 is_test_mode_), 492 false)); 493 shared_ptr<FilesystemCopierAction> filesystem_verifier_action( 494 new FilesystemCopierAction(false, true)); 495 shared_ptr<FilesystemCopierAction> kernel_filesystem_verifier_action( 496 new FilesystemCopierAction(true, true)); 497 shared_ptr<OmahaRequestAction> update_complete_action( 498 new OmahaRequestAction(system_state_, 499 new OmahaEvent(OmahaEvent::kTypeUpdateComplete), 500 new LibcurlHttpFetcher(GetProxyResolver(), 501 system_state_, 502 is_test_mode_), 503 false)); 504 505 download_action->set_delegate(this); 506 response_handler_action_ = response_handler_action; 507 download_action_ = download_action; 508 509 actions_.push_back(shared_ptr<AbstractAction>(update_check_action)); 510 actions_.push_back(shared_ptr<AbstractAction>(response_handler_action)); 511 actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action)); 512 actions_.push_back(shared_ptr<AbstractAction>( 513 kernel_filesystem_copier_action)); 514 actions_.push_back(shared_ptr<AbstractAction>(download_started_action)); 515 actions_.push_back(shared_ptr<AbstractAction>(download_action)); 516 actions_.push_back(shared_ptr<AbstractAction>(download_finished_action)); 517 actions_.push_back(shared_ptr<AbstractAction>(filesystem_verifier_action)); 518 actions_.push_back(shared_ptr<AbstractAction>( 519 kernel_filesystem_verifier_action)); 520 521 // Bond them together. We have to use the leaf-types when calling 522 // BondActions(). 523 BondActions(update_check_action.get(), 524 response_handler_action.get()); 525 BondActions(response_handler_action.get(), 526 filesystem_copier_action.get()); 527 BondActions(filesystem_copier_action.get(), 528 kernel_filesystem_copier_action.get()); 529 BondActions(kernel_filesystem_copier_action.get(), 530 download_action.get()); 531 BondActions(download_action.get(), 532 filesystem_verifier_action.get()); 533 BondActions(filesystem_verifier_action.get(), 534 kernel_filesystem_verifier_action.get()); 535 536 BuildPostInstallActions(kernel_filesystem_verifier_action.get()); 537 538 actions_.push_back(shared_ptr<AbstractAction>(update_complete_action)); 539 540 // Enqueue the actions 541 for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin(); 542 it != actions_.end(); ++it) { 543 processor_->EnqueueAction(it->get()); 544 } 545} 546 547bool UpdateAttempter::Rollback(bool powerwash) { 548 CHECK(!processor_->IsRunning()); 549 processor_->set_delegate(this); 550 551 // TODO(sosa): crbug.com/252539 -- refactor channel into system_state and 552 // check for != stable-channel here. 553 RefreshDevicePolicy(); 554 555 LOG(INFO) << "Setting rollback options."; 556 InstallPlan install_plan; 557 TEST_AND_RETURN_FALSE(utils::GetInstallDev(utils::BootDevice(), 558 &install_plan.install_path)); 559 install_plan.kernel_install_path = utils::BootKernelDevice( 560 install_plan.install_path); 561 install_plan.powerwash_required = powerwash; 562 563 LOG(INFO) << "Using this install plan:"; 564 install_plan.Dump(); 565 566 shared_ptr<InstallPlanAction> install_plan_action( 567 new InstallPlanAction(install_plan)); 568 actions_.push_back(shared_ptr<AbstractAction>(install_plan_action)); 569 570 // Initialize the default request params. 571 if (!omaha_request_params_->Init("", "", true)) { 572 LOG(ERROR) << "Unable to initialize Omaha request params."; 573 return false; 574 } 575 576 BuildPostInstallActions(install_plan_action.get()); 577 578 // Enqueue the actions 579 for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin(); 580 it != actions_.end(); ++it) { 581 processor_->EnqueueAction(it->get()); 582 } 583 584 // Update the payload state for Rollback. 585 system_state_->payload_state()->Rollback(); 586 587 SetStatusAndNotify(UPDATE_STATUS_ATTEMPTING_ROLLBACK, 588 kUpdateNoticeUnspecified); 589 590 // Just in case we didn't update boot flags yet, make sure they're updated 591 // before any update processing starts. This also schedules the start of the 592 // actions we just posted. 593 start_action_processor_ = true; 594 UpdateBootFlags(); 595 return true; 596} 597 598void UpdateAttempter::CheckForUpdate(const string& app_version, 599 const string& omaha_url, 600 bool interactive) { 601 LOG(INFO) << "New update check requested"; 602 603 if (status_ != UPDATE_STATUS_IDLE) { 604 LOG(INFO) << "Skipping update check because current status is " 605 << UpdateStatusToString(status_); 606 return; 607 } 608 609 // Read GPIO signals and determine whether this is an automated test scenario. 610 // For safety, we only allow a test update to be performed once; subsequent 611 // update requests will be carried out normally. 612 bool is_test_mode = (!is_test_update_attempted_ && 613 system_state_->gpio_handler()->IsTestModeSignaled()); 614 if (is_test_mode) { 615 LOG(WARNING) << "this is a test mode update attempt!"; 616 is_test_update_attempted_ = true; 617 } 618 619 // Pass through the interactive flag, in case we want to simulate a scheduled 620 // test. 621 Update(app_version, omaha_url, true, interactive, is_test_mode); 622} 623 624bool UpdateAttempter::RebootIfNeeded() { 625 if (status_ != UPDATE_STATUS_UPDATED_NEED_REBOOT) { 626 LOG(INFO) << "Reboot requested, but status is " 627 << UpdateStatusToString(status_) << ", so not rebooting."; 628 return false; 629 } 630 TEST_AND_RETURN_FALSE(utils::Reboot()); 631 return true; 632} 633 634// Delegate methods: 635void UpdateAttempter::ProcessingDone(const ActionProcessor* processor, 636 ErrorCode code) { 637 LOG(INFO) << "Processing Done."; 638 actions_.clear(); 639 640 // Reset cpu shares back to normal. 641 CleanupCpuSharesManagement(); 642 643 if (status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) { 644 LOG(INFO) << "Error event sent."; 645 646 // Inform scheduler of new status; also specifically inform about a failed 647 // update attempt with a test address. 648 SetStatusAndNotify(UPDATE_STATUS_IDLE, 649 (is_using_test_url_ ? kUpdateNoticeTestAddrFailed : 650 kUpdateNoticeUnspecified)); 651 652 if (!fake_update_success_) { 653 return; 654 } 655 LOG(INFO) << "Booted from FW B and tried to install new firmware, " 656 "so requesting reboot from user."; 657 } 658 659 if (code == kErrorCodeSuccess) { 660 utils::WriteFile(kUpdateCompletedMarker, "", 0); 661 prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0); 662 prefs_->SetString(kPrefsPreviousVersion, 663 omaha_request_params_->app_version()); 664 DeltaPerformer::ResetUpdateProgress(prefs_, false); 665 666 system_state_->payload_state()->UpdateSucceeded(); 667 668 // Since we're done with scattering fully at this point, this is the 669 // safest point delete the state files, as we're sure that the status is 670 // set to reboot (which means no more updates will be applied until reboot) 671 // This deletion is required for correctness as we want the next update 672 // check to re-create a new random number for the update check count. 673 // Similarly, we also delete the wall-clock-wait period that was persisted 674 // so that we start with a new random value for the next update check 675 // after reboot so that the same device is not favored or punished in any 676 // way. 677 prefs_->Delete(kPrefsUpdateCheckCount); 678 prefs_->Delete(kPrefsWallClockWaitPeriod); 679 prefs_->Delete(kPrefsUpdateFirstSeenAt); 680 681 SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT, 682 kUpdateNoticeUnspecified); 683 LOG(INFO) << "Update successfully applied, waiting to reboot."; 684 685 // Also report the success code so that the percentiles can be 686 // interpreted properly for the remaining error codes in UMA. 687 utils::SendErrorCodeToUma(system_state_, code); 688 return; 689 } 690 691 if (ScheduleErrorEventAction()) { 692 return; 693 } 694 LOG(INFO) << "No update."; 695 SetStatusAndNotify(UPDATE_STATUS_IDLE, kUpdateNoticeUnspecified); 696} 697 698void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) { 699 // Reset cpu shares back to normal. 700 CleanupCpuSharesManagement(); 701 download_progress_ = 0.0; 702 SetStatusAndNotify(UPDATE_STATUS_IDLE, kUpdateNoticeUnspecified); 703 actions_.clear(); 704 error_event_.reset(NULL); 705} 706 707// Called whenever an action has finished processing, either successfully 708// or otherwise. 709void UpdateAttempter::ActionCompleted(ActionProcessor* processor, 710 AbstractAction* action, 711 ErrorCode code) { 712 // Reset download progress regardless of whether or not the download 713 // action succeeded. Also, get the response code from HTTP request 714 // actions (update download as well as the initial update check 715 // actions). 716 const string type = action->Type(); 717 if (type == DownloadAction::StaticType()) { 718 download_progress_ = 0.0; 719 DownloadAction* download_action = dynamic_cast<DownloadAction*>(action); 720 http_response_code_ = download_action->GetHTTPResponseCode(); 721 } else if (type == OmahaRequestAction::StaticType()) { 722 OmahaRequestAction* omaha_request_action = 723 dynamic_cast<OmahaRequestAction*>(action); 724 // If the request is not an event, then it's the update-check. 725 if (!omaha_request_action->IsEvent()) { 726 http_response_code_ = omaha_request_action->GetHTTPResponseCode(); 727 // Forward the server-dictated poll interval to the update check 728 // scheduler, if any. 729 if (update_check_scheduler_) { 730 update_check_scheduler_->set_poll_interval( 731 omaha_request_action->GetOutputObject().poll_interval); 732 } 733 } 734 } 735 if (code != kErrorCodeSuccess) { 736 // If the current state is at or past the download phase, count the failure 737 // in case a switch to full update becomes necessary. Ignore network 738 // transfer timeouts and failures. 739 if (status_ >= UPDATE_STATUS_DOWNLOADING && 740 code != kErrorCodeDownloadTransferError) { 741 MarkDeltaUpdateFailure(); 742 } 743 // On failure, schedule an error event to be sent to Omaha. 744 CreatePendingErrorEvent(action, code); 745 return; 746 } 747 // Find out which action completed. 748 if (type == OmahaResponseHandlerAction::StaticType()) { 749 // Note that the status will be updated to DOWNLOADING when some bytes get 750 // actually downloaded from the server and the BytesReceived callback is 751 // invoked. This avoids notifying the user that a download has started in 752 // cases when the server and the client are unable to initiate the download. 753 CHECK(action == response_handler_action_.get()); 754 const InstallPlan& plan = response_handler_action_->install_plan(); 755 last_checked_time_ = time(NULL); 756 // TODO(adlr): put version in InstallPlan 757 new_version_ = "0.0.0.0"; 758 new_payload_size_ = plan.payload_size; 759 SetupDownload(); 760 SetupCpuSharesManagement(); 761 SetStatusAndNotify(UPDATE_STATUS_UPDATE_AVAILABLE, 762 kUpdateNoticeUnspecified); 763 } else if (type == DownloadAction::StaticType()) { 764 SetStatusAndNotify(UPDATE_STATUS_FINALIZING, kUpdateNoticeUnspecified); 765 } 766} 767 768// Stop updating. An attempt will be made to record status to the disk 769// so that updates can be resumed later. 770void UpdateAttempter::Terminate() { 771 // TODO(adlr): implement this method. 772 NOTIMPLEMENTED(); 773} 774 775// Try to resume from a previously Terminate()d update. 776void UpdateAttempter::ResumeUpdating() { 777 // TODO(adlr): implement this method. 778 NOTIMPLEMENTED(); 779} 780 781void UpdateAttempter::SetDownloadStatus(bool active) { 782 download_active_ = active; 783 LOG(INFO) << "Download status: " << (active ? "active" : "inactive"); 784} 785 786void UpdateAttempter::BytesReceived(uint64_t bytes_received, uint64_t total) { 787 if (!download_active_) { 788 LOG(ERROR) << "BytesReceived called while not downloading."; 789 return; 790 } 791 double progress = static_cast<double>(bytes_received) / 792 static_cast<double>(total); 793 // Self throttle based on progress. Also send notifications if 794 // progress is too slow. 795 const double kDeltaPercent = 0.01; // 1% 796 if (status_ != UPDATE_STATUS_DOWNLOADING || 797 bytes_received == total || 798 progress - download_progress_ >= kDeltaPercent || 799 TimeTicks::Now() - last_notify_time_ >= TimeDelta::FromSeconds(10)) { 800 download_progress_ = progress; 801 SetStatusAndNotify(UPDATE_STATUS_DOWNLOADING, kUpdateNoticeUnspecified); 802 } 803} 804 805bool UpdateAttempter::ResetStatus() { 806 LOG(INFO) << "Attempting to reset state from " 807 << UpdateStatusToString(status_) << " to UPDATE_STATUS_IDLE"; 808 809 switch (status_) { 810 case UPDATE_STATUS_IDLE: 811 // no-op. 812 return true; 813 814 case UPDATE_STATUS_UPDATED_NEED_REBOOT: { 815 bool ret_value = true; 816 status_ = UPDATE_STATUS_IDLE; 817 LOG(INFO) << "Reset Successful"; 818 819 // Remove the reboot marker so that if the machine is rebooted 820 // after resetting to idle state, it doesn't go back to 821 // UPDATE_STATUS_UPDATED_NEED_REBOOT state. 822 const FilePath kUpdateCompletedMarkerPath(kUpdateCompletedMarker); 823 if (!file_util::Delete(kUpdateCompletedMarkerPath, false)) 824 ret_value = false; 825 826 return ret_value; 827 } 828 829 default: 830 LOG(ERROR) << "Reset not allowed in this state."; 831 return false; 832 } 833} 834 835bool UpdateAttempter::GetStatus(int64_t* last_checked_time, 836 double* progress, 837 string* current_operation, 838 string* new_version, 839 int64_t* new_payload_size) { 840 *last_checked_time = last_checked_time_; 841 *progress = download_progress_; 842 *current_operation = UpdateStatusToString(status_); 843 *new_version = new_version_; 844 *new_payload_size = new_payload_size_; 845 return true; 846} 847 848void UpdateAttempter::UpdateBootFlags() { 849 if (update_boot_flags_running_) { 850 LOG(INFO) << "Update boot flags running, nothing to do."; 851 return; 852 } 853 if (updated_boot_flags_) { 854 LOG(INFO) << "Already updated boot flags. Skipping."; 855 if (start_action_processor_) { 856 ScheduleProcessingStart(); 857 } 858 return; 859 } 860 // This is purely best effort. Failures should be logged by Subprocess. Run 861 // the script asynchronously to avoid blocking the event loop regardless of 862 // the script runtime. 863 update_boot_flags_running_ = true; 864 LOG(INFO) << "Updating boot flags..."; 865 vector<string> cmd(1, "/usr/sbin/chromeos-setgoodkernel"); 866 if (!Subprocess::Get().Exec(cmd, StaticCompleteUpdateBootFlags, this)) { 867 CompleteUpdateBootFlags(1); 868 } 869} 870 871void UpdateAttempter::CompleteUpdateBootFlags(int return_code) { 872 update_boot_flags_running_ = false; 873 updated_boot_flags_ = true; 874 if (start_action_processor_) { 875 ScheduleProcessingStart(); 876 } 877} 878 879void UpdateAttempter::StaticCompleteUpdateBootFlags( 880 int return_code, 881 const string& output, 882 void* p) { 883 reinterpret_cast<UpdateAttempter*>(p)->CompleteUpdateBootFlags(return_code); 884} 885 886void UpdateAttempter::BroadcastStatus() { 887 if (!dbus_service_) { 888 return; 889 } 890 last_notify_time_ = TimeTicks::Now(); 891 update_engine_service_emit_status_update( 892 dbus_service_, 893 last_checked_time_, 894 download_progress_, 895 UpdateStatusToString(status_), 896 new_version_.c_str(), 897 new_payload_size_); 898} 899 900uint32_t UpdateAttempter::GetErrorCodeFlags() { 901 uint32_t flags = 0; 902 903 if (!utils::IsNormalBootMode()) 904 flags |= kErrorCodeDevModeFlag; 905 906 if (response_handler_action_.get() && 907 response_handler_action_->install_plan().is_resume) 908 flags |= kErrorCodeResumedFlag; 909 910 if (!utils::IsOfficialBuild()) 911 flags |= kErrorCodeTestImageFlag; 912 913 if (omaha_request_params_->update_url() != kProductionOmahaUrl) 914 flags |= kErrorCodeTestOmahaUrlFlag; 915 916 return flags; 917} 918 919bool UpdateAttempter::ShouldCancel(ErrorCode* cancel_reason) { 920 // Check if the channel we're attempting to update to is the same as the 921 // target channel currently chosen by the user. 922 OmahaRequestParams* params = system_state_->request_params(); 923 if (params->download_channel() != params->target_channel()) { 924 LOG(ERROR) << "Aborting download as target channel: " 925 << params->target_channel() 926 << " is different from the download channel: " 927 << params->download_channel(); 928 *cancel_reason = kErrorCodeUpdateCanceledByChannelChange; 929 return true; 930 } 931 932 return false; 933} 934 935void UpdateAttempter::SetStatusAndNotify(UpdateStatus status, 936 UpdateNotice notice) { 937 status_ = status; 938 if (update_check_scheduler_) { 939 update_check_scheduler_->SetUpdateStatus(status_, notice); 940 } 941 BroadcastStatus(); 942} 943 944void UpdateAttempter::CreatePendingErrorEvent(AbstractAction* action, 945 ErrorCode code) { 946 if (error_event_.get()) { 947 // This shouldn't really happen. 948 LOG(WARNING) << "There's already an existing pending error event."; 949 return; 950 } 951 952 // For now assume that a generic Omaha response action failure means that 953 // there's no update so don't send an event. Also, double check that the 954 // failure has not occurred while sending an error event -- in which case 955 // don't schedule another. This shouldn't really happen but just in case... 956 if ((action->Type() == OmahaResponseHandlerAction::StaticType() && 957 code == kErrorCodeError) || 958 status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) { 959 return; 960 } 961 962 // Classify the code to generate the appropriate result so that 963 // the Borgmon charts show up the results correctly. 964 // Do this before calling GetErrorCodeForAction which could potentially 965 // augment the bit representation of code and thus cause no matches for 966 // the switch cases below. 967 OmahaEvent::Result event_result; 968 switch (code) { 969 case kErrorCodeOmahaUpdateIgnoredPerPolicy: 970 case kErrorCodeOmahaUpdateDeferredPerPolicy: 971 case kErrorCodeOmahaUpdateDeferredForBackoff: 972 event_result = OmahaEvent::kResultUpdateDeferred; 973 break; 974 default: 975 event_result = OmahaEvent::kResultError; 976 break; 977 } 978 979 code = GetErrorCodeForAction(action, code); 980 fake_update_success_ = code == kErrorCodePostinstallBootedFromFirmwareB; 981 982 // Compute the final error code with all the bit flags to be sent to Omaha. 983 code = static_cast<ErrorCode>(code | GetErrorCodeFlags()); 984 error_event_.reset(new OmahaEvent(OmahaEvent::kTypeUpdateComplete, 985 event_result, 986 code)); 987} 988 989bool UpdateAttempter::ScheduleErrorEventAction() { 990 if (error_event_.get() == NULL) 991 return false; 992 993 LOG(ERROR) << "Update failed."; 994 system_state_->payload_state()->UpdateFailed(error_event_->error_code); 995 996 // Send it to Uma. 997 LOG(INFO) << "Reporting the error event"; 998 utils::SendErrorCodeToUma(system_state_, error_event_->error_code); 999 1000 // Send it to Omaha. 1001 shared_ptr<OmahaRequestAction> error_event_action( 1002 new OmahaRequestAction(system_state_, 1003 error_event_.release(), // Pass ownership. 1004 new LibcurlHttpFetcher(GetProxyResolver(), 1005 system_state_, 1006 is_test_mode_), 1007 false)); 1008 actions_.push_back(shared_ptr<AbstractAction>(error_event_action)); 1009 processor_->EnqueueAction(error_event_action.get()); 1010 SetStatusAndNotify(UPDATE_STATUS_REPORTING_ERROR_EVENT, 1011 kUpdateNoticeUnspecified); 1012 processor_->StartProcessing(); 1013 return true; 1014} 1015 1016void UpdateAttempter::SetCpuShares(utils::CpuShares shares) { 1017 if (shares_ == shares) { 1018 return; 1019 } 1020 if (utils::SetCpuShares(shares)) { 1021 shares_ = shares; 1022 LOG(INFO) << "CPU shares = " << shares_; 1023 } 1024} 1025 1026void UpdateAttempter::SetupCpuSharesManagement() { 1027 if (manage_shares_source_) { 1028 LOG(ERROR) << "Cpu shares timeout source hasn't been destroyed."; 1029 CleanupCpuSharesManagement(); 1030 } 1031 const int kCpuSharesTimeout = 2 * 60 * 60; // 2 hours 1032 manage_shares_source_ = g_timeout_source_new_seconds(kCpuSharesTimeout); 1033 g_source_set_callback(manage_shares_source_, 1034 StaticManageCpuSharesCallback, 1035 this, 1036 NULL); 1037 g_source_attach(manage_shares_source_, NULL); 1038 SetCpuShares(utils::kCpuSharesLow); 1039} 1040 1041void UpdateAttempter::CleanupCpuSharesManagement() { 1042 if (manage_shares_source_) { 1043 g_source_destroy(manage_shares_source_); 1044 manage_shares_source_ = NULL; 1045 } 1046 SetCpuShares(utils::kCpuSharesNormal); 1047} 1048 1049gboolean UpdateAttempter::StaticManageCpuSharesCallback(gpointer data) { 1050 return reinterpret_cast<UpdateAttempter*>(data)->ManageCpuSharesCallback(); 1051} 1052 1053gboolean UpdateAttempter::StaticStartProcessing(gpointer data) { 1054 reinterpret_cast<UpdateAttempter*>(data)->processor_->StartProcessing(); 1055 return FALSE; // Don't call this callback again. 1056} 1057 1058void UpdateAttempter::ScheduleProcessingStart() { 1059 LOG(INFO) << "Scheduling an action processor start."; 1060 start_action_processor_ = false; 1061 g_idle_add(&StaticStartProcessing, this); 1062} 1063 1064bool UpdateAttempter::ManageCpuSharesCallback() { 1065 SetCpuShares(utils::kCpuSharesNormal); 1066 manage_shares_source_ = NULL; 1067 return false; // Destroy the timeout source. 1068} 1069 1070void UpdateAttempter::DisableDeltaUpdateIfNeeded() { 1071 int64_t delta_failures; 1072 if (omaha_request_params_->delta_okay() && 1073 prefs_->GetInt64(kPrefsDeltaUpdateFailures, &delta_failures) && 1074 delta_failures >= kMaxDeltaUpdateFailures) { 1075 LOG(WARNING) << "Too many delta update failures, forcing full update."; 1076 omaha_request_params_->set_delta_okay(false); 1077 } 1078} 1079 1080void UpdateAttempter::MarkDeltaUpdateFailure() { 1081 // Don't try to resume a failed delta update. 1082 DeltaPerformer::ResetUpdateProgress(prefs_, false); 1083 int64_t delta_failures; 1084 if (!prefs_->GetInt64(kPrefsDeltaUpdateFailures, &delta_failures) || 1085 delta_failures < 0) { 1086 delta_failures = 0; 1087 } 1088 prefs_->SetInt64(kPrefsDeltaUpdateFailures, ++delta_failures); 1089} 1090 1091void UpdateAttempter::SetupDownload() { 1092 MultiRangeHttpFetcher* fetcher = 1093 dynamic_cast<MultiRangeHttpFetcher*>(download_action_->http_fetcher()); 1094 fetcher->ClearRanges(); 1095 if (response_handler_action_->install_plan().is_resume) { 1096 // Resuming an update so fetch the update manifest metadata first. 1097 int64_t manifest_metadata_size = 0; 1098 prefs_->GetInt64(kPrefsManifestMetadataSize, &manifest_metadata_size); 1099 fetcher->AddRange(0, manifest_metadata_size); 1100 // If there're remaining unprocessed data blobs, fetch them. Be careful not 1101 // to request data beyond the end of the payload to avoid 416 HTTP response 1102 // error codes. 1103 int64_t next_data_offset = 0; 1104 prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, &next_data_offset); 1105 uint64_t resume_offset = manifest_metadata_size + next_data_offset; 1106 if (resume_offset < response_handler_action_->install_plan().payload_size) { 1107 fetcher->AddRange(resume_offset); 1108 } 1109 } else { 1110 fetcher->AddRange(0); 1111 } 1112} 1113 1114void UpdateAttempter::PingOmaha() { 1115 if (!processor_->IsRunning()) { 1116 shared_ptr<OmahaRequestAction> ping_action( 1117 new OmahaRequestAction(system_state_, 1118 NULL, 1119 new LibcurlHttpFetcher(GetProxyResolver(), 1120 system_state_, 1121 is_test_mode_), 1122 true)); 1123 actions_.push_back(shared_ptr<OmahaRequestAction>(ping_action)); 1124 processor_->set_delegate(NULL); 1125 processor_->EnqueueAction(ping_action.get()); 1126 // Call StartProcessing() synchronously here to avoid any race conditions 1127 // caused by multiple outstanding ping Omaha requests. If we call 1128 // StartProcessing() asynchronously, the device can be suspended before we 1129 // get a chance to callback to StartProcessing(). When the device resumes 1130 // (assuming the device sleeps longer than the next update check period), 1131 // StartProcessing() is called back and at the same time, the next update 1132 // check is fired which eventually invokes StartProcessing(). A crash 1133 // can occur because StartProcessing() checks to make sure that the 1134 // processor is idle which it isn't due to the two concurrent ping Omaha 1135 // requests. 1136 processor_->StartProcessing(); 1137 } else { 1138 LOG(WARNING) << "Action processor running, Omaha ping suppressed."; 1139 } 1140 1141 // Update the status which will schedule the next update check 1142 SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT, 1143 kUpdateNoticeUnspecified); 1144} 1145 1146 1147bool UpdateAttempter::DecrementUpdateCheckCount() { 1148 int64 update_check_count_value; 1149 1150 if (!prefs_->Exists(kPrefsUpdateCheckCount)) { 1151 // This file does not exist. This means we haven't started our update 1152 // check count down yet, so nothing more to do. This file will be created 1153 // later when we first satisfy the wall-clock-based-wait period. 1154 LOG(INFO) << "No existing update check count. That's normal."; 1155 return true; 1156 } 1157 1158 if (prefs_->GetInt64(kPrefsUpdateCheckCount, &update_check_count_value)) { 1159 // Only if we're able to read a proper integer value, then go ahead 1160 // and decrement and write back the result in the same file, if needed. 1161 LOG(INFO) << "Update check count = " << update_check_count_value; 1162 1163 if (update_check_count_value == 0) { 1164 // It could be 0, if, for some reason, the file didn't get deleted 1165 // when we set our status to waiting for reboot. so we just leave it 1166 // as is so that we can prevent another update_check wait for this client. 1167 LOG(INFO) << "Not decrementing update check count as it's already 0."; 1168 return true; 1169 } 1170 1171 if (update_check_count_value > 0) 1172 update_check_count_value--; 1173 else 1174 update_check_count_value = 0; 1175 1176 // Write out the new value of update_check_count_value. 1177 if (prefs_->SetInt64(kPrefsUpdateCheckCount, update_check_count_value)) { 1178 // We successfully wrote out te new value, so enable the 1179 // update check based wait. 1180 LOG(INFO) << "New update check count = " << update_check_count_value; 1181 return true; 1182 } 1183 } 1184 1185 LOG(INFO) << "Deleting update check count state due to read/write errors."; 1186 1187 // We cannot read/write to the file, so disable the update check based wait 1188 // so that we don't get stuck in this OS version by any chance (which could 1189 // happen if there's some bug that causes to read/write incorrectly). 1190 // Also attempt to delete the file to do our best effort to cleanup. 1191 prefs_->Delete(kPrefsUpdateCheckCount); 1192 return false; 1193} 1194 1195void UpdateAttempter::UpdateEngineStarted() { 1196 system_state_->payload_state()->UpdateEngineStarted(); 1197} 1198 1199} // namespace chromeos_update_engine 1200