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