1 // 2 // Copyright (C) 2012 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 #ifndef UPDATE_ENGINE_CROS_PAYLOAD_STATE_H_ 18 #define UPDATE_ENGINE_CROS_PAYLOAD_STATE_H_ 19 20 #include <algorithm> 21 #include <string> 22 #include <vector> 23 24 #include <base/time/time.h> 25 #include <gtest/gtest_prod.h> // for FRIEND_TEST 26 27 #include "update_engine/common/excluder_interface.h" 28 #include "update_engine/common/metrics_constants.h" 29 #include "update_engine/common/prefs_interface.h" 30 #include "update_engine/cros/payload_state_interface.h" 31 32 namespace chromeos_update_engine { 33 34 class SystemState; 35 36 // Encapsulates all the payload state required for download. This includes the 37 // state necessary for handling multiple URLs in Omaha response, the backoff 38 // state, etc. All state is persisted so that we use the most recently saved 39 // value when resuming the update_engine process. All state is also cached in 40 // memory so that we ensure we always make progress based on last known good 41 // state even when there's any issue in reading/writing from the file system. 42 class PayloadState : public PayloadStateInterface { 43 public: 44 PayloadState(); ~PayloadState()45 ~PayloadState() override {} 46 47 // Initializes a payload state object using the given global system state. 48 // It performs the initial loading of all persisted state into memory and 49 // dumps the initial state for debugging purposes. Note: the other methods 50 // should be called only after calling Initialize on this object. 51 bool Initialize(); 52 53 // Implementation of PayloadStateInterface methods. 54 void SetResponse(const OmahaResponse& response) override; 55 void DownloadComplete() override; 56 void DownloadProgress(size_t count) override; 57 void UpdateResumed() override; 58 void UpdateRestarted() override; 59 void UpdateSucceeded() override; 60 void UpdateFailed(ErrorCode error) override; 61 void ResetUpdateStatus() override; 62 bool ShouldBackoffDownload() override; 63 void Rollback() override; 64 void ExpectRebootInNewVersion(const std::string& target_version_uid) override; 65 void SetUsingP2PForDownloading(bool value) override; 66 SetUsingP2PForSharing(bool value)67 void SetUsingP2PForSharing(bool value) override { 68 using_p2p_for_sharing_ = value; 69 } 70 GetResponseSignature()71 inline std::string GetResponseSignature() override { 72 return response_signature_; 73 } 74 GetFullPayloadAttemptNumber()75 inline int GetFullPayloadAttemptNumber() override { 76 return full_payload_attempt_number_; 77 } 78 GetPayloadAttemptNumber()79 inline int GetPayloadAttemptNumber() override { 80 return payload_attempt_number_; 81 } 82 GetCurrentUrl()83 inline std::string GetCurrentUrl() override { 84 return (payload_index_ < candidate_urls_.size() && 85 url_index_ < candidate_urls_[payload_index_].size()) 86 ? candidate_urls_[payload_index_][url_index_] 87 : ""; 88 } 89 GetUrlFailureCount()90 inline uint32_t GetUrlFailureCount() override { return url_failure_count_; } 91 GetUrlSwitchCount()92 inline uint32_t GetUrlSwitchCount() override { return url_switch_count_; } 93 GetNumResponsesSeen()94 inline int GetNumResponsesSeen() override { return num_responses_seen_; } 95 GetBackoffExpiryTime()96 inline base::Time GetBackoffExpiryTime() override { 97 return backoff_expiry_time_; 98 } 99 100 base::TimeDelta GetUpdateDuration() override; 101 102 base::TimeDelta GetUpdateDurationUptime() override; 103 GetCurrentBytesDownloaded(DownloadSource source)104 inline uint64_t GetCurrentBytesDownloaded(DownloadSource source) override { 105 return source < kNumDownloadSources ? current_bytes_downloaded_[source] : 0; 106 } 107 GetTotalBytesDownloaded(DownloadSource source)108 inline uint64_t GetTotalBytesDownloaded(DownloadSource source) override { 109 return source < kNumDownloadSources ? total_bytes_downloaded_[source] : 0; 110 } 111 GetNumReboots()112 inline uint32_t GetNumReboots() override { return num_reboots_; } 113 114 void UpdateEngineStarted() override; 115 GetRollbackHappened()116 inline bool GetRollbackHappened() override { return rollback_happened_; } 117 118 void SetRollbackHappened(bool rollback_happened) override; 119 GetRollbackVersion()120 inline std::string GetRollbackVersion() override { return rollback_version_; } 121 122 int GetP2PNumAttempts() override; 123 base::Time GetP2PFirstAttemptTimestamp() override; 124 void P2PNewAttempt() override; 125 bool P2PAttemptAllowed() override; 126 GetUsingP2PForDownloading()127 bool GetUsingP2PForDownloading() const override { 128 return using_p2p_for_downloading_; 129 } 130 GetUsingP2PForSharing()131 bool GetUsingP2PForSharing() const override { return using_p2p_for_sharing_; } 132 GetScatteringWaitPeriod()133 base::TimeDelta GetScatteringWaitPeriod() override { 134 return scattering_wait_period_; 135 } 136 137 void SetScatteringWaitPeriod(base::TimeDelta wait_period) override; 138 139 void SetStagingWaitPeriod(base::TimeDelta wait_period) override; 140 SetP2PUrl(const std::string & url)141 void SetP2PUrl(const std::string& url) override { p2p_url_ = url; } 142 GetP2PUrl()143 std::string GetP2PUrl() const override { return p2p_url_; } 144 145 bool NextPayload() override; 146 147 private: 148 enum class AttemptType { 149 kUpdate, 150 kRollback, 151 }; 152 153 friend class PayloadStateTest; 154 FRIEND_TEST(PayloadStateTest, RebootAfterUpdateFailedMetric); 155 FRIEND_TEST(PayloadStateTest, RebootAfterUpdateSucceed); 156 FRIEND_TEST(PayloadStateTest, RebootAfterCanceledUpdate); 157 FRIEND_TEST(PayloadStateTest, RollbackHappened); 158 FRIEND_TEST(PayloadStateTest, RollbackVersion); 159 FRIEND_TEST(PayloadStateTest, UpdateSuccessWithWipedPrefs); 160 FRIEND_TEST(PayloadStateTest, NextPayloadResetsUrlIndex); 161 FRIEND_TEST(PayloadStateTest, ExcludeNoopForNonExcludables); 162 FRIEND_TEST(PayloadStateTest, ExcludeOnlyCanExcludables); 163 FRIEND_TEST(PayloadStateTest, IncrementFailureExclusionTest); 164 FRIEND_TEST(PayloadStateTest, HaltExclusionPostPayloadExhaustion); 165 FRIEND_TEST(PayloadStateTest, NonInfinitePayloadIndexIncrement); 166 167 // Helper called when an attempt has begun, is called by 168 // UpdateResumed(), UpdateRestarted() and Rollback(). 169 void AttemptStarted(AttemptType attempt_type); 170 171 // Increments the payload attempt number used for metrics. 172 void IncrementPayloadAttemptNumber(); 173 174 // Increments the payload attempt number which governs the backoff behavior 175 // at the time of the next update check. 176 void IncrementFullPayloadAttemptNumber(); 177 178 // Advances the current URL index to the next available one. If all URLs have 179 // been exhausted during the current payload download attempt (as indicated 180 // by the payload attempt number), then it will increment the payload attempt 181 // number and wrap around again with the first URL in the list. This also 182 // updates the URL switch count, if needed. 183 void IncrementUrlIndex(); 184 185 // Increments the failure count of the current URL. If the configured max 186 // failure count is reached for this URL, it advances the current URL index 187 // to the next URL and resets the failure count for that URL. 188 void IncrementFailureCount(); 189 190 // Excludes the current payload + current candidate URL from being part of 191 // future updates/retries. Whenever |SetResponse()| or |NextPayload()| decide 192 // on the initial current URL index and the next payload respectively, it will 193 // advanced based on exclusions. 194 void ExcludeCurrentPayload(); 195 196 // Updates the backoff expiry time exponentially based on the current 197 // payload attempt number. 198 void UpdateBackoffExpiryTime(); 199 200 // Updates the value of current download source based on the current URL 201 // index. If the download source is not one of the known sources, it's set 202 // to kNumDownloadSources. 203 void UpdateCurrentDownloadSource(); 204 205 // Updates the various metrics corresponding with the given number of bytes 206 // that were downloaded recently. 207 void UpdateBytesDownloaded(size_t count); 208 209 // Calculates the PayloadType we're using. 210 PayloadType CalculatePayloadType(); 211 212 // Collects and reports the various metrics related to an update attempt. 213 void CollectAndReportAttemptMetrics(ErrorCode code); 214 215 // Persists values related to the UpdateEngine.Attempt.* metrics so 216 // we can identify later if an update attempt ends abnormally. 217 void PersistAttemptMetrics(); 218 219 // Clears persistent state previously set using AttemptMetricsPersist(). 220 void ClearPersistedAttemptMetrics(); 221 222 // Checks if persistent state previously set using AttemptMetricsPersist() 223 // exists and, if so, emits it with |attempt_result| set to 224 // metrics::AttemptResult::kAbnormalTermination. 225 void ReportAndClearPersistedAttemptMetrics(); 226 227 // Collects and reports the various metrics related to a successful update. 228 void CollectAndReportSuccessfulUpdateMetrics(); 229 230 // Checks if we were expecting to be running in the new version but the 231 // boot into the new version failed for some reason. If that's the case, an 232 // UMA metric is sent reporting the number of attempts the same applied 233 // payload was attempted to reboot. This function is called by UpdateAttempter 234 // every time the update engine starts and there's no reboot pending. 235 void ReportFailedBootIfNeeded(); 236 237 // Resets all the persisted state values which are maintained relative to the 238 // current response signature. The response signature itself is not reset. 239 void ResetPersistedState(); 240 241 // Resets the appropriate state related to download sources that need to be 242 // reset on a new update. 243 void ResetDownloadSourcesOnNewUpdate(); 244 245 // Calculates the response "signature", which is basically a string composed 246 // of the subset of the fields in the current response that affect the 247 // behavior of the PayloadState. 248 std::string CalculateResponseSignature(); 249 250 // Initializes the current response signature from the persisted state. 251 void LoadResponseSignature(); 252 253 // Sets the response signature to the given value. Also persists the value 254 // being set so that we resume from the save value in case of a process 255 // restart. 256 void SetResponseSignature(const std::string& response_signature); 257 258 // Initializes the payload attempt number from the persisted state. 259 void LoadPayloadAttemptNumber(); 260 261 // Initializes the payload attempt number for full payloads from the persisted 262 // state. 263 void LoadFullPayloadAttemptNumber(); 264 265 // Sets the payload attempt number to the given value. Also persists the 266 // value being set so that we resume from the same value in case of a process 267 // restart. 268 void SetPayloadAttemptNumber(int payload_attempt_number); 269 270 // Sets the payload attempt number for full updates to the given value. Also 271 // persists the value being set so that we resume from the same value in case 272 // of a process restart. 273 void SetFullPayloadAttemptNumber(int payload_attempt_number); 274 275 // Sets the current payload index to the given value. Also persists the value 276 // being set so that we resume from the same value in case of a process 277 // restart. 278 void SetPayloadIndex(size_t payload_index); 279 280 // Initializes the current URL index from the persisted state. 281 void LoadUrlIndex(); 282 283 // Sets the current URL index to the given value. Also persists the value 284 // being set so that we resume from the same value in case of a process 285 // restart. 286 void SetUrlIndex(uint32_t url_index); 287 288 // Initializes the current URL's failure count from the persisted stae. 289 void LoadUrlFailureCount(); 290 291 // Sets the current URL's failure count to the given value. Also persists the 292 // value being set so that we resume from the same value in case of a process 293 // restart. 294 void SetUrlFailureCount(uint32_t url_failure_count); 295 296 // Sets |url_switch_count_| to the given value and persists the value. 297 void SetUrlSwitchCount(uint32_t url_switch_count); 298 299 // Initializes |url_switch_count_| from the persisted stae. 300 void LoadUrlSwitchCount(); 301 302 // Initializes the backoff expiry time from the persisted state. 303 void LoadBackoffExpiryTime(); 304 305 // Sets the backoff expiry time to the given value. Also persists the value 306 // being set so that we resume from the same value in case of a process 307 // restart. 308 void SetBackoffExpiryTime(const base::Time& new_time); 309 310 // Initializes |update_timestamp_start_| from the persisted state. 311 void LoadUpdateTimestampStart(); 312 313 // Sets |update_timestamp_start_| to the given value and persists the value. 314 void SetUpdateTimestampStart(const base::Time& value); 315 316 // Sets |update_timestamp_end_| to the given value. This is not persisted 317 // as it happens at the end of the update process where state is deleted 318 // anyway. 319 void SetUpdateTimestampEnd(const base::Time& value); 320 321 // Initializes |update_duration_uptime_| from the persisted state. 322 void LoadUpdateDurationUptime(); 323 324 // Helper method used in SetUpdateDurationUptime() and 325 // CalculateUpdateDurationUptime(). 326 void SetUpdateDurationUptimeExtended(const base::TimeDelta& value, 327 const base::Time& timestamp, 328 bool use_logging); 329 330 // Sets |update_duration_uptime_| to the given value and persists 331 // the value and sets |update_duration_uptime_timestamp_| to the 332 // current monotonic time. 333 void SetUpdateDurationUptime(const base::TimeDelta& value); 334 335 // Adds the difference between current monotonic time and 336 // |update_duration_uptime_timestamp_| to |update_duration_uptime_| and 337 // sets |update_duration_uptime_timestamp_| to current monotonic time. 338 void CalculateUpdateDurationUptime(); 339 340 // Returns the full key for a download source given the prefix. 341 std::string GetPrefsKey(const std::string& prefix, DownloadSource source); 342 343 // Loads the number of bytes that have been currently downloaded through the 344 // previous attempts from the persisted state for the given source. It's 345 // reset to 0 every time we begin a full update and is continued from previous 346 // attempt if we're resuming the update. 347 void LoadCurrentBytesDownloaded(DownloadSource source); 348 349 // Sets the number of bytes that have been currently downloaded for the 350 // given source. This value is also persisted. 351 void SetCurrentBytesDownloaded(DownloadSource source, 352 uint64_t current_bytes_downloaded, 353 bool log); 354 355 // Loads the total number of bytes that have been downloaded (since the last 356 // successful update) from the persisted state for the given source. It's 357 // reset to 0 every time we successfully apply an update and counts the bytes 358 // downloaded for both successful and failed attempts since then. 359 void LoadTotalBytesDownloaded(DownloadSource source); 360 361 // Sets the total number of bytes that have been downloaded so far for the 362 // given source. This value is also persisted. 363 void SetTotalBytesDownloaded(DownloadSource source, 364 uint64_t total_bytes_downloaded, 365 bool log); 366 367 // Loads whether rollback has happened on this device since the last update 368 // check where policy was available. This info is preserved over powerwash. 369 void LoadRollbackHappened(); 370 371 // Loads the excluded version from our prefs file. 372 void LoadRollbackVersion(); 373 374 // Excludes this version from getting AU'd to until we receive a new update 375 // response. 376 void SetRollbackVersion(const std::string& rollback_version); 377 378 // Clears any excluded version. 379 void ResetRollbackVersion(); 380 GetUrlIndex()381 inline uint32_t GetUrlIndex() { 382 return (url_index_ != 0 && payload_index_ < candidate_urls_.size()) 383 ? std::min(candidate_urls_[payload_index_].size() - 1, 384 url_index_) 385 : 0; 386 } 387 388 // Computes the list of candidate URLs from the total list of payload URLs in 389 // the Omaha response. 390 void ComputeCandidateUrls(); 391 392 // Sets |num_responses_seen_| and persist it to disk. 393 void SetNumResponsesSeen(int num_responses_seen); 394 395 // Initializes |num_responses_seen_| from persisted state. 396 void LoadNumResponsesSeen(); 397 398 // Initializes |num_reboots_| from the persisted state. 399 void LoadNumReboots(); 400 401 // Sets |num_reboots| for the update attempt. Also persists the 402 // value being set so that we resume from the same value in case of a process 403 // restart. 404 void SetNumReboots(uint32_t num_reboots); 405 406 // Checks to see if the device rebooted since the last call and if so 407 // increments num_reboots. 408 void UpdateNumReboots(); 409 410 // Loads the |kPrefsP2PFirstAttemptTimestamp| state variable from disk 411 // into |p2p_first_attempt_timestamp_|. 412 void LoadP2PFirstAttemptTimestamp(); 413 414 // Loads the |kPrefsP2PNumAttempts| state variable into |p2p_num_attempts_|. 415 void LoadP2PNumAttempts(); 416 417 // Sets the |kPrefsP2PNumAttempts| state variable to |value|. 418 void SetP2PNumAttempts(int value); 419 420 // Sets the |kPrefsP2PFirstAttemptTimestamp| state variable to |time|. 421 void SetP2PFirstAttemptTimestamp(const base::Time& time); 422 423 // Loads the persisted scattering wallclock-based wait period. 424 void LoadScatteringWaitPeriod(); 425 426 // Loads the persisted staging wallclock-based wait period. 427 void LoadStagingWaitPeriod(); 428 429 // Get the total size of all payloads. 430 int64_t GetPayloadSize(); 431 432 // Interface object with which we read/write persisted state. This must 433 // be set by calling the Initialize method before calling any other method. 434 PrefsInterface* prefs_; 435 436 // Interface object with which we read/write persisted state. This must 437 // be set by calling the Initialize method before calling any other method. 438 // This object persists across powerwashes. 439 PrefsInterface* powerwash_safe_prefs_; 440 441 // Interface object with which we determine exclusion decisions for 442 // payloads/partitions during the update. This must be set by calling the 443 // Initialize method before calling any other method. 444 ExcluderInterface* excluder_; 445 446 // This is the current response object from Omaha. 447 OmahaResponse response_; 448 449 // Whether P2P is being used for downloading and sharing. 450 bool using_p2p_for_downloading_; 451 bool using_p2p_for_sharing_; 452 453 // Stores the P2P download URL, if one is used. 454 std::string p2p_url_; 455 456 // The cached value of |kPrefsP2PFirstAttemptTimestamp|. 457 base::Time p2p_first_attempt_timestamp_; 458 459 // The cached value of |kPrefsP2PNumAttempts|. 460 int p2p_num_attempts_; 461 462 // This stores a "signature" of the current response. The signature here 463 // refers to a subset of the current response from Omaha. Each update to 464 // this value is persisted so we resume from the same value in case of a 465 // process restart. 466 std::string response_signature_; 467 468 // The number of times we've tried to download the payload. This is 469 // incremented each time we download the payload successsfully or when we 470 // exhaust all failure limits for all URLs and are about to wrap around back 471 // to the first URL. Each update to this value is persisted so we resume from 472 // the same value in case of a process restart. 473 int payload_attempt_number_; 474 475 // The number of times we've tried to download the payload in full. This is 476 // incremented each time we download the payload in full successsfully or 477 // when we exhaust all failure limits for all URLs and are about to wrap 478 // around back to the first URL. Each update to this value is persisted so 479 // we resume from the same value in case of a process restart. 480 int full_payload_attempt_number_; 481 482 // The index of the current payload. 483 size_t payload_index_ = 0; 484 485 // The index of the current URL. This type is different from the one in the 486 // accessor methods because |PrefsInterface| supports only int64_t but we want 487 // to provide a stronger abstraction of uint32_t. Each update to this value 488 // is persisted so we resume from the same value in case of a process restart. 489 size_t url_index_; 490 491 // The count of failures encountered in the current attempt to download using 492 // the current URL (specified by url_index_). Each update to this value is 493 // persisted so we resume from the same value in case of a process restart. 494 int64_t url_failure_count_; 495 496 // The number of times we've switched URLs. 497 int32_t url_switch_count_; 498 499 // The current download source based on the current URL. This value is 500 // not persisted as it can be recomputed every time we update the URL. 501 // We're storing this so as not to recompute this on every few bytes of 502 // data we read from the socket. 503 DownloadSource current_download_source_; 504 505 // The number of different Omaha responses seen. Increases every time 506 // a new response is seen. Resets to 0 only when the system has been 507 // successfully updated. 508 int num_responses_seen_; 509 510 // The number of system reboots during an update attempt. Technically since 511 // we don't go out of our way to not update it when not attempting an update, 512 // also records the number of reboots before the next update attempt starts. 513 uint32_t num_reboots_; 514 515 // The timestamp until which we've to wait before attempting to download the 516 // payload again, so as to backoff repeated downloads. 517 base::Time backoff_expiry_time_; 518 519 // The most recently calculated value of the update duration. 520 base::TimeDelta update_duration_current_; 521 522 // The point in time (wall-clock) that the update was started. 523 base::Time update_timestamp_start_; 524 525 // The point in time (wall-clock) that the update ended. If the update 526 // is still in progress, this is set to the Epoch (e.g. 0). 527 base::Time update_timestamp_end_; 528 529 // The update duration uptime 530 base::TimeDelta update_duration_uptime_; 531 532 // The monotonic time when |update_duration_uptime_| was last set 533 base::Time update_duration_uptime_timestamp_; 534 535 // The number of bytes that have been downloaded for each source for each new 536 // update attempt. If we resume an update, we'll continue from the previous 537 // value, but if we get a new response or if the previous attempt failed, 538 // we'll reset this to 0 to start afresh. Each update to this value is 539 // persisted so we resume from the same value in case of a process restart. 540 // The extra index in the array is to no-op accidental access in case the 541 // return value from GetCurrentDownloadSource is used without validation. 542 uint64_t current_bytes_downloaded_[kNumDownloadSources + 1]; 543 544 // The number of bytes that have been downloaded for each source since the 545 // the last successful update. This is used to compute the overhead we incur. 546 // Each update to this value is persisted so we resume from the same value in 547 // case of a process restart. 548 // The extra index in the array is to no-op accidental access in case the 549 // return value from GetCurrentDownloadSource is used without validation. 550 uint64_t total_bytes_downloaded_[kNumDownloadSources + 1]; 551 552 // A small timespan used when comparing wall-clock times for coping 553 // with the fact that clocks drift and consequently are adjusted 554 // (either forwards or backwards) via NTP. 555 static const base::TimeDelta kDurationSlack; 556 557 // The ordered list of the subset of payload URL candidates which are 558 // allowed as per device policy. 559 std::vector<std::vector<std::string>> candidate_urls_; 560 561 // This stores whether rollback has happened since the last time device policy 562 // was available during update check. When this is set, we're preventing 563 // forced updates to avoid update-rollback loops. 564 bool rollback_happened_; 565 566 // This stores an excluded version set as part of rollback. When we rollback 567 // we store the version of the os from which we are rolling back from in order 568 // to guarantee that we do not re-update to it on the next au attempt after 569 // reboot. 570 std::string rollback_version_; 571 572 // The number of bytes downloaded per attempt. 573 int64_t attempt_num_bytes_downloaded_; 574 575 // The boot time when the attempt was started. 576 base::Time attempt_start_time_boot_; 577 578 // The monotonic time when the attempt was started. 579 base::Time attempt_start_time_monotonic_; 580 581 // The connection type when the attempt started. 582 metrics::ConnectionType attempt_connection_type_; 583 584 // Whether we're currently rolling back. 585 AttemptType attempt_type_; 586 587 // The current scattering wallclock-based wait period. 588 base::TimeDelta scattering_wait_period_; 589 590 // The current staging wallclock-based wait period. 591 base::TimeDelta staging_wait_period_; 592 593 DISALLOW_COPY_AND_ASSIGN(PayloadState); 594 }; 595 596 } // namespace chromeos_update_engine 597 598 #endif // UPDATE_ENGINE_CROS_PAYLOAD_STATE_H_ 599