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/excluder_interface.h"
28 #include "update_engine/common/prefs_interface.h"
29 #include "update_engine/metrics_constants.h"
30 #include "update_engine/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(SystemState* system_state);
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 
165   // Helper called when an attempt has begun, is called by
166   // UpdateResumed(), UpdateRestarted() and Rollback().
167   void AttemptStarted(AttemptType attempt_type);
168 
169   // Increments the payload attempt number used for metrics.
170   void IncrementPayloadAttemptNumber();
171 
172   // Increments the payload attempt number which governs the backoff behavior
173   // at the time of the next update check.
174   void IncrementFullPayloadAttemptNumber();
175 
176   // Advances the current URL index to the next available one. If all URLs have
177   // been exhausted during the current payload download attempt (as indicated
178   // by the payload attempt number), then it will increment the payload attempt
179   // number and wrap around again with the first URL in the list. This also
180   // updates the URL switch count, if needed.
181   void IncrementUrlIndex();
182 
183   // Increments the failure count of the current URL. If the configured max
184   // failure count is reached for this URL, it advances the current URL index
185   // to the next URL and resets the failure count for that URL.
186   void IncrementFailureCount();
187 
188   // Excludes the current payload + current candidate URL from being part of
189   // future updates/retries. Whenever |SetResponse()| or |NextPayload()| decide
190   // on the initial current URL index and the next payload respectively, it will
191   // advanced based on exclusions.
192   void ExcludeCurrentPayload();
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   // Calculates the response "signature", which is basically a string composed
244   // of the subset of the fields in the current response that affect the
245   // behavior of the PayloadState.
246   std::string CalculateResponseSignature();
247 
248   // Initializes the current response signature from the persisted state.
249   void LoadResponseSignature();
250 
251   // Sets the response signature to the given value. Also persists the value
252   // being set so that we resume from the save value in case of a process
253   // restart.
254   void SetResponseSignature(const std::string& response_signature);
255 
256   // Initializes the payload attempt number from the persisted state.
257   void LoadPayloadAttemptNumber();
258 
259   // Initializes the payload attempt number for full payloads from the persisted
260   // state.
261   void LoadFullPayloadAttemptNumber();
262 
263   // Sets the payload attempt number to the given value. Also persists the
264   // value being set so that we resume from the same value in case of a process
265   // restart.
266   void SetPayloadAttemptNumber(int payload_attempt_number);
267 
268   // Sets the payload attempt number for full updates to the given value. Also
269   // persists the value being set so that we resume from the same value in case
270   // of a process restart.
271   void SetFullPayloadAttemptNumber(int payload_attempt_number);
272 
273   // Sets the current payload index to the given value. Also persists the value
274   // being set so that we resume from the same value in case of a process
275   // restart.
276   void SetPayloadIndex(size_t payload_index);
277 
278   // Initializes the current URL index from the persisted state.
279   void LoadUrlIndex();
280 
281   // Sets the current URL index to the given value. Also persists the value
282   // being set so that we resume from the same value in case of a process
283   // restart.
284   void SetUrlIndex(uint32_t url_index);
285 
286   // Initializes the current URL's failure count from the persisted stae.
287   void LoadUrlFailureCount();
288 
289   // Sets the current URL's failure count to the given value. Also persists the
290   // value being set so that we resume from the same value in case of a process
291   // restart.
292   void SetUrlFailureCount(uint32_t url_failure_count);
293 
294   // Sets |url_switch_count_| to the given value and persists the value.
295   void SetUrlSwitchCount(uint32_t url_switch_count);
296 
297   // Initializes |url_switch_count_| from the persisted stae.
298   void LoadUrlSwitchCount();
299 
300   // Initializes the backoff expiry time from the persisted state.
301   void LoadBackoffExpiryTime();
302 
303   // Sets the backoff expiry time to the given value. Also persists the value
304   // being set so that we resume from the same value in case of a process
305   // restart.
306   void SetBackoffExpiryTime(const base::Time& new_time);
307 
308   // Initializes |update_timestamp_start_| from the persisted state.
309   void LoadUpdateTimestampStart();
310 
311   // Sets |update_timestamp_start_| to the given value and persists the value.
312   void SetUpdateTimestampStart(const base::Time& value);
313 
314   // Sets |update_timestamp_end_| to the given value. This is not persisted
315   // as it happens at the end of the update process where state is deleted
316   // anyway.
317   void SetUpdateTimestampEnd(const base::Time& value);
318 
319   // Initializes |update_duration_uptime_| from the persisted state.
320   void LoadUpdateDurationUptime();
321 
322   // Helper method used in SetUpdateDurationUptime() and
323   // CalculateUpdateDurationUptime().
324   void SetUpdateDurationUptimeExtended(const base::TimeDelta& value,
325                                        const base::Time& timestamp,
326                                        bool use_logging);
327 
328   // Sets |update_duration_uptime_| to the given value and persists
329   // the value and sets |update_duration_uptime_timestamp_| to the
330   // current monotonic time.
331   void SetUpdateDurationUptime(const base::TimeDelta& value);
332 
333   // Adds the difference between current monotonic time and
334   // |update_duration_uptime_timestamp_| to |update_duration_uptime_| and
335   // sets |update_duration_uptime_timestamp_| to current monotonic time.
336   void CalculateUpdateDurationUptime();
337 
338   // Returns the full key for a download source given the prefix.
339   std::string GetPrefsKey(const std::string& prefix, DownloadSource source);
340 
341   // Loads the number of bytes that have been currently downloaded through the
342   // previous attempts from the persisted state for the given source. It's
343   // reset to 0 every time we begin a full update and is continued from previous
344   // attempt if we're resuming the update.
345   void LoadCurrentBytesDownloaded(DownloadSource source);
346 
347   // Sets the number of bytes that have been currently downloaded for the
348   // given source. This value is also persisted.
349   void SetCurrentBytesDownloaded(DownloadSource source,
350                                  uint64_t current_bytes_downloaded,
351                                  bool log);
352 
353   // Loads the total number of bytes that have been downloaded (since the last
354   // successful update) from the persisted state for the given source. It's
355   // reset to 0 every time we successfully apply an update and counts the bytes
356   // downloaded for both successful and failed attempts since then.
357   void LoadTotalBytesDownloaded(DownloadSource source);
358 
359   // Sets the total number of bytes that have been downloaded so far for the
360   // given source. This value is also persisted.
361   void SetTotalBytesDownloaded(DownloadSource source,
362                                uint64_t total_bytes_downloaded,
363                                bool log);
364 
365   // Loads whether rollback has happened on this device since the last update
366   // check where policy was available. This info is preserved over powerwash.
367   void LoadRollbackHappened();
368 
369   // Loads the excluded version from our prefs file.
370   void LoadRollbackVersion();
371 
372   // Excludes 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 excluded version.
377   void ResetRollbackVersion();
378 
GetUrlIndex()379   inline uint32_t GetUrlIndex() {
380     return (url_index_ != 0 && payload_index_ < candidate_urls_.size())
381                ? std::min(candidate_urls_[payload_index_].size() - 1,
382                           url_index_)
383                : 0;
384   }
385 
386   // Computes the list of candidate URLs from the total list of payload URLs in
387   // the Omaha response.
388   void ComputeCandidateUrls();
389 
390   // Sets |num_responses_seen_| and persist it to disk.
391   void SetNumResponsesSeen(int num_responses_seen);
392 
393   // Initializes |num_responses_seen_| from persisted state.
394   void LoadNumResponsesSeen();
395 
396   // Initializes |num_reboots_| from the persisted state.
397   void LoadNumReboots();
398 
399   // Sets |num_reboots| for the update attempt. Also persists the
400   // value being set so that we resume from the same value in case of a process
401   // restart.
402   void SetNumReboots(uint32_t num_reboots);
403 
404   // Checks to see if the device rebooted since the last call and if so
405   // increments num_reboots.
406   void UpdateNumReboots();
407 
408   // Loads the |kPrefsP2PFirstAttemptTimestamp| state variable from disk
409   // into |p2p_first_attempt_timestamp_|.
410   void LoadP2PFirstAttemptTimestamp();
411 
412   // Loads the |kPrefsP2PNumAttempts| state variable into |p2p_num_attempts_|.
413   void LoadP2PNumAttempts();
414 
415   // Sets the |kPrefsP2PNumAttempts| state variable to |value|.
416   void SetP2PNumAttempts(int value);
417 
418   // Sets the |kPrefsP2PFirstAttemptTimestamp| state variable to |time|.
419   void SetP2PFirstAttemptTimestamp(const base::Time& time);
420 
421   // Loads the persisted scattering wallclock-based wait period.
422   void LoadScatteringWaitPeriod();
423 
424   // Loads the persisted staging wallclock-based wait period.
425   void LoadStagingWaitPeriod();
426 
427   // Get the total size of all payloads.
428   int64_t GetPayloadSize();
429 
430   // The global state of the system.
431   SystemState* system_state_;
432 
433   // Interface object with which we read/write persisted state. This must
434   // be set by calling the Initialize method before calling any other method.
435   PrefsInterface* prefs_;
436 
437   // Interface object with which we read/write persisted state. This must
438   // be set by calling the Initialize method before calling any other method.
439   // This object persists across powerwashes.
440   PrefsInterface* powerwash_safe_prefs_;
441 
442   // Interface object with which we determine exclusion decisions for
443   // payloads/partitions during the update. This must be set by calling the
444   // Initialize method before calling any other method.
445   ExcluderInterface* excluder_;
446 
447   // This is the current response object from Omaha.
448   OmahaResponse response_;
449 
450   // Whether P2P is being used for downloading and sharing.
451   bool using_p2p_for_downloading_;
452   bool using_p2p_for_sharing_;
453 
454   // Stores the P2P download URL, if one is used.
455   std::string p2p_url_;
456 
457   // The cached value of |kPrefsP2PFirstAttemptTimestamp|.
458   base::Time p2p_first_attempt_timestamp_;
459 
460   // The cached value of |kPrefsP2PNumAttempts|.
461   int p2p_num_attempts_;
462 
463   // This stores a "signature" of the current response. The signature here
464   // refers to a subset of the current response from Omaha.  Each update to
465   // this value is persisted so we resume from the same value in case of a
466   // process restart.
467   std::string response_signature_;
468 
469   // The number of times we've tried to download the payload. This is
470   // incremented each time we download the payload successsfully or when we
471   // exhaust all failure limits for all URLs and are about to wrap around back
472   // to the first URL.  Each update to this value is persisted so we resume from
473   // the same value in case of a process restart.
474   int payload_attempt_number_;
475 
476   // The number of times we've tried to download the payload in full. This is
477   // incremented each time we download the payload in full successsfully or
478   // when we exhaust all failure limits for all URLs and are about to wrap
479   // around back to the first URL.  Each update to this value is persisted so
480   // we resume from the same value in case of a process restart.
481   int full_payload_attempt_number_;
482 
483   // The index of the current payload.
484   size_t payload_index_ = 0;
485 
486   // The index of the current URL.  This type is different from the one in the
487   // accessor methods because PrefsInterface supports only int64_t but we want
488   // to provide a stronger abstraction of uint32_t.  Each update to this value
489   // is persisted so we resume from the same value in case of a process
490   // restart.
491   size_t url_index_;
492 
493   // The count of failures encountered in the current attempt to download using
494   // the current URL (specified by url_index_).  Each update to this value is
495   // persisted so we resume from the same value in case of a process restart.
496   int64_t url_failure_count_;
497 
498   // The number of times we've switched URLs.
499   int32_t url_switch_count_;
500 
501   // The current download source based on the current URL. This value is
502   // not persisted as it can be recomputed every time we update the URL.
503   // We're storing this so as not to recompute this on every few bytes of
504   // data we read from the socket.
505   DownloadSource current_download_source_;
506 
507   // The number of different Omaha responses seen. Increases every time
508   // a new response is seen. Resets to 0 only when the system has been
509   // successfully updated.
510   int num_responses_seen_;
511 
512   // The number of system reboots during an update attempt. Technically since
513   // we don't go out of our way to not update it when not attempting an update,
514   // also records the number of reboots before the next update attempt starts.
515   uint32_t num_reboots_;
516 
517   // The timestamp until which we've to wait before attempting to download the
518   // payload again, so as to backoff repeated downloads.
519   base::Time backoff_expiry_time_;
520 
521   // The most recently calculated value of the update duration.
522   base::TimeDelta update_duration_current_;
523 
524   // The point in time (wall-clock) that the update was started.
525   base::Time update_timestamp_start_;
526 
527   // The point in time (wall-clock) that the update ended. If the update
528   // is still in progress, this is set to the Epoch (e.g. 0).
529   base::Time update_timestamp_end_;
530 
531   // The update duration uptime
532   base::TimeDelta update_duration_uptime_;
533 
534   // The monotonic time when |update_duration_uptime_| was last set
535   base::Time update_duration_uptime_timestamp_;
536 
537   // The number of bytes that have been downloaded for each source for each new
538   // update attempt. If we resume an update, we'll continue from the previous
539   // value, but if we get a new response or if the previous attempt failed,
540   // we'll reset this to 0 to start afresh. Each update to this value is
541   // persisted so we resume from the same value in case of a process restart.
542   // The extra index in the array is to no-op accidental access in case the
543   // return value from GetCurrentDownloadSource is used without validation.
544   uint64_t current_bytes_downloaded_[kNumDownloadSources + 1];
545 
546   // The number of bytes that have been downloaded for each source since the
547   // the last successful update. This is used to compute the overhead we incur.
548   // Each update to this value is persisted so we resume from the same value in
549   // case of a process restart.
550   // The extra index in the array is to no-op accidental access in case the
551   // return value from GetCurrentDownloadSource is used without validation.
552   uint64_t total_bytes_downloaded_[kNumDownloadSources + 1];
553 
554   // A small timespan used when comparing wall-clock times for coping
555   // with the fact that clocks drift and consequently are adjusted
556   // (either forwards or backwards) via NTP.
557   static const base::TimeDelta kDurationSlack;
558 
559   // The ordered list of the subset of payload URL candidates which are
560   // allowed as per device policy.
561   std::vector<std::vector<std::string>> candidate_urls_;
562 
563   // This stores whether rollback has happened since the last time device policy
564   // was available during update check. When this is set, we're preventing
565   // forced updates to avoid update-rollback loops.
566   bool rollback_happened_;
567 
568   // This stores an excluded version set as part of rollback. When we rollback
569   // we store the version of the os from which we are rolling back from in order
570   // to guarantee that we do not re-update to it on the next au attempt after
571   // reboot.
572   std::string rollback_version_;
573 
574   // The number of bytes downloaded per attempt.
575   int64_t attempt_num_bytes_downloaded_;
576 
577   // The boot time when the attempt was started.
578   base::Time attempt_start_time_boot_;
579 
580   // The monotonic time when the attempt was started.
581   base::Time attempt_start_time_monotonic_;
582 
583   // The connection type when the attempt started.
584   metrics::ConnectionType attempt_connection_type_;
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   // The current staging wallclock-based wait period.
593   base::TimeDelta staging_wait_period_;
594 
595   DISALLOW_COPY_AND_ASSIGN(PayloadState);
596 };
597 
598 }  // namespace chromeos_update_engine
599 
600 #endif  // UPDATE_ENGINE_PAYLOAD_STATE_H_
601