1 //
2 // Copyright (C) 2014 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_UPDATE_MANAGER_CHROMEOS_POLICY_H_
18 #define UPDATE_ENGINE_UPDATE_MANAGER_CHROMEOS_POLICY_H_
19 
20 #include <string>
21 
22 #include <base/time/time.h>
23 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
24 
25 #include "update_engine/update_manager/policy.h"
26 #include "update_engine/update_manager/prng.h"
27 
28 namespace chromeos_update_manager {
29 
30 // Output information from UpdateBackoffAndDownloadUrl.
31 struct UpdateBackoffAndDownloadUrlResult {
32   // Whether the failed attempt count (maintained by the caller) needs to be
33   // incremented.
34   bool do_increment_failures;
35   // The current backoff expiry. Null if backoff is not in effect.
36   base::Time backoff_expiry;
37   // The new URL index to use and number of download errors associated with it.
38   // Significant iff |do_increment_failures| is false and |backoff_expiry| is
39   // null. Negative value means no usable URL was found.
40   int url_idx;
41   int url_num_errors;
42 };
43 
44 // Parameters for update scattering, as returned by UpdateScattering.
45 struct UpdateScatteringResult {
46   bool is_scattering;
47   base::TimeDelta wait_period;
48   int check_threshold;
49 };
50 
51 // ChromeOSPolicy implements the policy-related logic used in ChromeOS.
52 class ChromeOSPolicy : public Policy {
53  public:
ChromeOSPolicy()54   ChromeOSPolicy() {}
~ChromeOSPolicy()55   ~ChromeOSPolicy() override {}
56 
57   // Policy overrides.
58   EvalStatus UpdateCheckAllowed(
59       EvaluationContext* ec, State* state, std::string* error,
60       UpdateCheckParams* result) const override;
61 
62   EvalStatus UpdateCanStart(
63       EvaluationContext* ec,
64       State* state,
65       std::string* error,
66       UpdateDownloadParams* result,
67       UpdateState update_state) const override;
68 
69   EvalStatus UpdateDownloadAllowed(
70       EvaluationContext* ec,
71       State* state,
72       std::string* error,
73       bool* result) const override;
74 
75   EvalStatus P2PEnabled(
76       EvaluationContext* ec,
77       State* state,
78       std::string* error,
79       bool* result) const override;
80 
81   EvalStatus P2PEnabledChanged(
82       EvaluationContext* ec,
83       State* state,
84       std::string* error,
85       bool* result,
86       bool prev_result) const override;
87 
88  protected:
89   // Policy override.
PolicyName()90   std::string PolicyName() const override { return "ChromeOSPolicy"; }
91 
92  private:
93   friend class UmChromeOSPolicyTest;
94   FRIEND_TEST(UmChromeOSPolicyTest,
95               FirstCheckIsAtMostInitialIntervalAfterStart);
96   FRIEND_TEST(UmChromeOSPolicyTest, RecurringCheckBaseIntervalAndFuzz);
97   FRIEND_TEST(UmChromeOSPolicyTest, RecurringCheckBackoffIntervalAndFuzz);
98   FRIEND_TEST(UmChromeOSPolicyTest, RecurringCheckServerDictatedPollInterval);
99   FRIEND_TEST(UmChromeOSPolicyTest, ExponentialBackoffIsCapped);
100   FRIEND_TEST(UmChromeOSPolicyTest, UpdateCheckAllowedWaitsForTheTimeout);
101   FRIEND_TEST(UmChromeOSPolicyTest, UpdateCheckAllowedWaitsForOOBE);
102   FRIEND_TEST(UmChromeOSPolicyTest,
103               UpdateCanStartNotAllowedScatteringNewWaitPeriodApplies);
104   FRIEND_TEST(UmChromeOSPolicyTest,
105               UpdateCanStartNotAllowedScatteringPrevWaitPeriodStillApplies);
106   FRIEND_TEST(UmChromeOSPolicyTest,
107               UpdateCanStartNotAllowedScatteringNewCountThresholdApplies);
108   FRIEND_TEST(UmChromeOSPolicyTest,
109               UpdateCanStartNotAllowedScatteringPrevCountThresholdStillApplies);
110   FRIEND_TEST(UmChromeOSPolicyTest, UpdateCanStartAllowedScatteringSatisfied);
111   FRIEND_TEST(UmChromeOSPolicyTest,
112               UpdateCanStartAllowedInteractivePreventsScattering);
113   FRIEND_TEST(UmChromeOSPolicyTest,
114               UpdateCanStartAllowedP2PDownloadingBlockedDueToNumAttempts);
115   FRIEND_TEST(UmChromeOSPolicyTest,
116               UpdateCanStartAllowedP2PDownloadingBlockedDueToAttemptsPeriod);
117 
118   // Auxiliary constant (zero by default).
119   const base::TimeDelta kZeroInterval;
120 
121   // Default update check timeout interval/fuzz values used to compute the
122   // NextUpdateCheckTime(), in seconds. Actual fuzz is within +/- half of the
123   // indicated value.
124   static const int kTimeoutInitialInterval;
125   static const int kTimeoutPeriodicInterval;
126   static const int kTimeoutMaxBackoffInterval;
127   static const int kTimeoutRegularFuzz;
128 
129   // Maximum update attempt backoff interval and fuzz.
130   static const int kAttemptBackoffMaxIntervalInDays;
131   static const int kAttemptBackoffFuzzInHours;
132 
133   // Maximum number of times we'll allow using P2P for the same update payload.
134   static const int kMaxP2PAttempts;
135   // Maximum period of time allowed for download a payload via P2P, in seconds.
136   static const int kMaxP2PAttemptsPeriodInSeconds;
137 
138   // A private policy implementation returning the wallclock timestamp when
139   // the next update check should happen.
140   // TODO(garnold) We should probably change that to infer a monotonic
141   // timestamp, which will make the update check intervals more resilient to
142   // clock skews. Might require switching some of the variables exported by the
143   // UpdaterProvider to report monotonic time, as well.
144   EvalStatus NextUpdateCheckTime(EvaluationContext* ec, State* state,
145                                  std::string* error,
146                                  base::Time* next_update_check) const;
147 
148   // Returns a TimeDelta based on the provided |interval| seconds +/- half
149   // |fuzz| seconds. The return value is guaranteed to be a non-negative
150   // TimeDelta.
151   static base::TimeDelta FuzzedInterval(PRNG* prng, int interval, int fuzz);
152 
153   // A private policy for determining backoff and the download URL to use.
154   // Within |update_state|, |backoff_expiry| and |is_backoff_disabled| are used
155   // for determining whether backoff is still in effect; if not,
156   // |download_errors| is scanned past |failures_last_updated|, and a new
157   // download URL from |download_urls| is found and written to |result->url_idx|
158   // (-1 means no usable URL exists); |download_errors_max| determines the
159   // maximum number of attempts per URL, according to the Omaha response. If an
160   // update failure is identified then |result->do_increment_failures| is set to
161   // true; if backoff is enabled, a new backoff period is computed (from the
162   // time of failure) based on |num_failures|. Otherwise, backoff expiry is
163   // nullified, indicating that no backoff is in effect.
164   //
165   // If backing off but the previous backoff expiry is unchanged, returns
166   // |EvalStatus::kAskMeAgainLater|. Otherwise:
167   //
168   // * If backing off with a new expiry time, then |result->backoff_expiry| is
169   //   set to this time.
170   //
171   // * Else, |result->backoff_expiry| is set to null, indicating that no backoff
172   //   is in effect.
173   //
174   // In any of these cases, returns |EvalStatus::kSucceeded|. If an error
175   // occurred, returns |EvalStatus::kFailed|.
176   EvalStatus UpdateBackoffAndDownloadUrl(
177       EvaluationContext* ec, State* state, std::string* error,
178       UpdateBackoffAndDownloadUrlResult* result,
179       const UpdateState& update_state) const;
180 
181   // A private policy for checking whether scattering is due. Writes in |result|
182   // the decision as to whether or not to scatter; a wallclock-based scatter
183   // wait period, which ranges from zero (do not wait) and no greater than the
184   // current scatter factor provided by the device policy (if available) or the
185   // maximum wait period determined by Omaha; and an update check-based
186   // threshold between zero (no threshold) and the maximum number determined by
187   // the update engine. Within |update_state|, |scatter_wait_period| should
188   // contain the last scattering period returned by this function, or zero if no
189   // wait period is known; |scatter_check_threshold| is the last update check
190   // threshold, or zero if no such threshold is known. If not scattering, or if
191   // any of the scattering values has changed, returns |EvalStatus::kSucceeded|;
192   // otherwise, |EvalStatus::kAskMeAgainLater|.
193   EvalStatus UpdateScattering(EvaluationContext* ec, State* state,
194                               std::string* error,
195                               UpdateScatteringResult* result,
196                               const UpdateState& update_state) const;
197 
198   DISALLOW_COPY_AND_ASSIGN(ChromeOSPolicy);
199 };
200 
201 }  // namespace chromeos_update_manager
202 
203 #endif  // UPDATE_ENGINE_UPDATE_MANAGER_CHROMEOS_POLICY_H_
204