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