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 
28 namespace chromeos_update_manager {
29 
30 // The three different results of a policy request.
31 enum class EvalStatus {
32   kFailed,
33   kSucceeded,
34   kAskMeAgainLater,
35 };
36 
37 std::string ToString(EvalStatus status);
38 
39 // Parameters of an update check. These parameters are determined by the
40 // UpdateCheckAllowed policy.
41 struct 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).
60 struct 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.
136 enum class UpdateCannotStartReason {
137   kUndefined,
138   kCheckDue,
139   kScattering,
140   kBackoff,
141   kCannotDownload,
142 };
143 
144 struct 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.
190 class Policy {
191  public:
~Policy()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>
PolicyRequestName(EvalStatus (Policy::* policy_method)(EvaluationContext *,State *,std::string *,R *,Args...)const)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:
Policy()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