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