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