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
28namespace chromeos_update_manager {
29
30// Output information from UpdateBackoffAndDownloadUrl.
31struct 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.
45struct 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.
52class ChromeOSPolicy : public Policy {
53 public:
54  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.
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