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_POLICY_H_
18#define UPDATE_ENGINE_UPDATE_MANAGER_POLICY_H_
19
20#include <string>
21#include <tuple>
22#include <vector>
23
24#include "update_engine/common/error_code.h"
25#include "update_engine/update_manager/evaluation_context.h"
26#include "update_engine/update_manager/state.h"
27
28namespace chromeos_update_manager {
29
30// The three different results of a policy request.
31enum class EvalStatus {
32  kFailed,
33  kSucceeded,
34  kAskMeAgainLater,
35};
36
37std::string ToString(EvalStatus status);
38
39// Parameters of an update check. These parameters are determined by the
40// UpdateCheckAllowed policy.
41struct UpdateCheckParams {
42  bool updates_enabled;  // Whether the auto-updates are enabled on this build.
43
44  // Attributes pertaining to the case where update checks are allowed.
45  //
46  // A target version prefix, if imposed by policy; otherwise, an empty string.
47  std::string target_version_prefix;
48  // A target channel, if so imposed by policy; otherwise, an empty string.
49  std::string target_channel;
50
51  // Whether the allowed update is interactive (user-initiated) or periodic.
52  bool is_interactive;
53};
54
55// Input arguments to UpdateCanStart.
56//
57// A snapshot of the state of the current update process. This includes
58// everything that a policy might need and that occurred since the first time
59// the current payload was first seen and attempted (consecutively).
60struct UpdateState {
61  // Information pertaining to the current update payload and/or check.
62  //
63  // Whether the current update check is an interactive one. The caller should
64  // feed the value returned by the preceding call to UpdateCheckAllowed().
65  bool is_interactive;
66  // Whether it is a delta payload.
67  bool is_delta_payload;
68  // Wallclock time when payload was first (consecutively) offered by Omaha.
69  base::Time first_seen;
70  // Number of consecutive update checks returning the current update.
71  int num_checks;
72  // Number of update payload failures and the wallclock time when it was last
73  // updated by the updater. These should both be nullified whenever a new
74  // update is seen; they are updated at the policy's descretion (via
75  // UpdateDownloadParams.do_increment_failures) once all of the usable download
76  // URLs for the payload have been used without success. They should be
77  // persisted across reboots.
78  int num_failures;
79  base::Time failures_last_updated;
80
81  // Information pertaining to downloading and applying of the current update.
82  //
83  // An array of download URLs provided by Omaha.
84  std::vector<std::string> download_urls;
85  // Max number of errors allowed per download URL.
86  int download_errors_max;
87  // The index of the URL to download from, as determined in the previous call
88  // to the policy. For a newly seen payload, this should be -1.
89  int last_download_url_idx;
90  // The number of successive download errors pertaining to this last URL, as
91  // determined in the previous call to the policy. For a newly seen payload,
92  // this should be zero.
93  int last_download_url_num_errors;
94  // An array of errors that occurred while trying to download this update since
95  // the previous call to this policy has returned, or since this payload was
96  // first seen, or since the updater process has started (whichever is later).
97  // Includes the URL index attempted, the error code, and the wallclock-based
98  // timestamp when it occurred.
99  std::vector<std::tuple<int, chromeos_update_engine::ErrorCode, base::Time>>
100      download_errors;
101  // Whether Omaha forbids use of P2P for downloading and/or sharing.
102  bool p2p_downloading_disabled;
103  bool p2p_sharing_disabled;
104  // The number of P2P download attempts and wallclock-based time when P2P
105  // download was first attempted.
106  int p2p_num_attempts;
107  base::Time p2p_first_attempted;
108
109  // Information pertaining to update backoff mechanism.
110  //
111  // The currently known (persisted) wallclock-based backoff expiration time;
112  // zero if none.
113  base::Time backoff_expiry;
114  // Whether backoff is disabled by Omaha.
115  bool is_backoff_disabled;
116
117  // Information pertaining to update scattering.
118  //
119  // The currently knwon (persisted) scattering wallclock-based wait period and
120  // update check threshold; zero if none.
121  base::TimeDelta scatter_wait_period;
122  int scatter_check_threshold;
123  // Maximum wait period allowed for this update, as determined by Omaha.
124  base::TimeDelta scatter_wait_period_max;
125  // Minimum/maximum check threshold values.
126  // TODO(garnold) These appear to not be related to the current update and so
127  // should probably be obtained as variables via UpdaterProvider.
128  int scatter_check_threshold_min;
129  int scatter_check_threshold_max;
130};
131
132// Results regarding the downloading and applying of an update, as determined by
133// UpdateCanStart.
134//
135// An enumerator for the reasons of not allowing an update to start.
136enum class UpdateCannotStartReason {
137  kUndefined,
138  kCheckDue,
139  kScattering,
140  kBackoff,
141  kCannotDownload,
142};
143
144struct UpdateDownloadParams {
145  // Whether the update attempt is allowed to proceed.
146  bool update_can_start;
147  // If update cannot proceed, a reason code for why it cannot do so.
148  UpdateCannotStartReason cannot_start_reason;
149
150  // Download related attributes. The update engine uses them to choose the
151  // means for downloading and applying an update.
152  //
153  // The index of the download URL to use (-1 means no suitable URL was found)
154  // and whether it can be used. Even if there's no URL or its use is not
155  // allowed (backoff, scattering) there may still be other means for download
156  // (like P2P).  The URL index needs to be persisted and handed back to the
157  // policy on the next time it is called.
158  int download_url_idx;
159  bool download_url_allowed;
160  // The number of download errors associated with this download URL. This value
161  // needs to be persisted and handed back to the policy on the next time it is
162  // called.
163  int download_url_num_errors;
164  // Whether P2P download and sharing are allowed.
165  bool p2p_downloading_allowed;
166  bool p2p_sharing_allowed;
167
168  // Other values that need to be persisted and handed to the policy as need on
169  // the next call.
170  //
171  // Whether an update failure has been identified by the policy. The client
172  // should increment and persist its update failure count, and record the time
173  // when this was done; it needs to hand these values back to the policy
174  // (UpdateState.{num_failures,failures_last_updated}) on the next time it is
175  // called.
176  bool do_increment_failures;
177  // The current backof expiry.
178  base::Time backoff_expiry;
179  // The scattering wait period and check threshold.
180  base::TimeDelta scatter_wait_period;
181  int scatter_check_threshold;
182};
183
184// The Policy class is an interface to the ensemble of policy requests that the
185// client can make. A derived class includes the policy implementations of
186// these.
187//
188// When compile-time selection of the policy is required due to missing or extra
189// parts in a given platform, a different Policy subclass can be used.
190class Policy {
191 public:
192  virtual ~Policy() {}
193
194  // Returns the name of a public policy request.
195  // IMPORTANT: Be sure to add a conditional for each new public policy that is
196  // being added to this class in the future.
197  template<typename R, typename... Args>
198  std::string PolicyRequestName(
199      EvalStatus (Policy::*policy_method)(EvaluationContext*, State*,
200                                          std::string*, R*,
201                                          Args...) const) const {
202    std::string class_name = PolicyName() + "::";
203
204    if (reinterpret_cast<typeof(&Policy::UpdateCheckAllowed)>(
205            policy_method) == &Policy::UpdateCheckAllowed)
206      return class_name + "UpdateCheckAllowed";
207    if (reinterpret_cast<typeof(&Policy::UpdateCanStart)>(
208            policy_method) == &Policy::UpdateCanStart)
209      return class_name + "UpdateCanStart";
210    if (reinterpret_cast<typeof(&Policy::UpdateDownloadAllowed)>(
211            policy_method) == &Policy::UpdateDownloadAllowed)
212      return class_name + "UpdateDownloadAllowed";
213    if (reinterpret_cast<typeof(&Policy::P2PEnabled)>(
214            policy_method) == &Policy::P2PEnabled)
215      return class_name + "P2PEnabled";
216    if (reinterpret_cast<typeof(&Policy::P2PEnabledChanged)>(
217            policy_method) == &Policy::P2PEnabledChanged)
218      return class_name + "P2PEnabledChanged";
219
220    NOTREACHED();
221    return class_name + "(unknown)";
222  }
223
224
225  // List of policy requests. A policy request takes an EvaluationContext as the
226  // first argument, a State instance, a returned error message, a returned
227  // value and optionally followed by one or more arbitrary constant arguments.
228  //
229  // When the implementation fails, the method returns EvalStatus::kFailed and
230  // sets the |error| string.
231
232  // UpdateCheckAllowed returns whether it is allowed to request an update check
233  // to Omaha.
234  virtual EvalStatus UpdateCheckAllowed(
235      EvaluationContext* ec, State* state, std::string* error,
236      UpdateCheckParams* result) const = 0;
237
238  // Returns EvalStatus::kSucceeded if either an update can start being
239  // processed, or the attempt needs to be aborted. In cases where the update
240  // needs to wait for some condition to be satisfied, but none of the values
241  // that need to be persisted has changed, returns
242  // EvalStatus::kAskMeAgainLater. Arguments include an |update_state| that
243  // encapsulates data pertaining to the current ongoing update process.
244  virtual EvalStatus UpdateCanStart(
245      EvaluationContext* ec,
246      State* state,
247      std::string* error,
248      UpdateDownloadParams* result,
249      UpdateState update_state) const = 0;
250
251  // Checks whether downloading of an update is allowed; currently, this checks
252  // whether the network connection type is suitable for updating over.  May
253  // consult the shill provider as well as the device policy (if available).
254  // Returns |EvalStatus::kSucceeded|, setting |result| according to whether or
255  // not the current connection can be used; on error, returns
256  // |EvalStatus::kFailed| and sets |error| accordingly.
257  virtual EvalStatus UpdateDownloadAllowed(
258      EvaluationContext* ec,
259      State* state,
260      std::string* error,
261      bool* result) const = 0;
262
263  // Checks whether P2P is enabled. This may consult device policy and other
264  // global settings.
265  virtual EvalStatus P2PEnabled(
266      EvaluationContext* ec, State* state, std::string* error,
267      bool* result) const = 0;
268
269  // Checks whether P2P is enabled, but blocks (returns
270  // |EvalStatus::kAskMeAgainLater|) until it is different from |prev_result|.
271  // If the P2P enabled status is not expected to change, will return
272  // immediately with |EvalStatus::kSucceeded|. This internally uses the
273  // P2PEnabled() policy above.
274  virtual EvalStatus P2PEnabledChanged(
275      EvaluationContext* ec, State* state, std::string* error,
276      bool* result, bool prev_result) const = 0;
277
278 protected:
279  Policy() {}
280
281  // Returns the name of the actual policy class.
282  virtual std::string PolicyName() const = 0;
283
284 private:
285  DISALLOW_COPY_AND_ASSIGN(Policy);
286};
287
288}  // namespace chromeos_update_manager
289
290#endif  // UPDATE_ENGINE_UPDATE_MANAGER_POLICY_H_
291