1 //
2 // Copyright (C) 2017 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 #include "update_engine/update_manager/android_things_policy.h"
18 
19 #include <string>
20 #include <vector>
21 
22 #include <base/logging.h>
23 #include <base/time/time.h>
24 
25 #include "update_engine/update_manager/api_restricted_downloads_policy_impl.h"
26 #include "update_engine/update_manager/enough_slots_ab_updates_policy_impl.h"
27 #include "update_engine/update_manager/interactive_update_policy_impl.h"
28 #include "update_engine/update_manager/official_build_check_policy_impl.h"
29 
30 using base::Time;
31 using chromeos_update_engine::ErrorCode;
32 using std::string;
33 using std::vector;
34 
35 namespace chromeos_update_manager {
36 
37 const NextUpdateCheckPolicyConstants
38     AndroidThingsPolicy::kNextUpdateCheckPolicyConstants = {
39         .timeout_initial_interval = 7 * 60,
40         .timeout_periodic_interval = 5 * 60 * 60,
41         .timeout_max_backoff_interval = 26 * 60 * 60,
42         .timeout_regular_fuzz = 10 * 60,
43         .attempt_backoff_max_interval_in_days = 16,
44         .attempt_backoff_fuzz_in_hours = 12,
45 };
46 
47 EvalStatus AndroidThingsPolicy::UpdateCheckAllowed(
48     EvaluationContext* ec,
49     State* state,
50     string* error,
51     UpdateCheckParams* result) const {
52   // Set the default return values.
53   result->updates_enabled = true;
54   result->target_channel.clear();
55   result->target_version_prefix.clear();
56   result->rollback_allowed = false;
57   result->rollback_allowed_milestones = -1;
58   result->interactive = false;
59 
60   // Build a list of policies to consult.  Note that each policy may modify the
61   // result structure, even if it signals kContinue.
62   EnoughSlotsAbUpdatesPolicyImpl enough_slots_ab_updates_policy;
63   OnlyUpdateOfficialBuildsPolicyImpl only_update_official_builds_policy;
64   InteractiveUpdatePolicyImpl interactive_update_policy;
65   NextUpdateCheckTimePolicyImpl next_update_check_time_policy(
66       kNextUpdateCheckPolicyConstants);
67 
68   vector<Policy const*> policies_to_consult = {
69       // Do not perform any updates if there are not enough slots to do
70       // A/B updates
71       &enough_slots_ab_updates_policy,
72 
73       // Check to see if an interactive update was requested.
74       &interactive_update_policy,
75 
76       // Unofficial builds should not perform periodic update checks.
77       &only_update_official_builds_policy,
78 
79       // Ensure that periodic update checks are timed properly.
80       &next_update_check_time_policy,
81   };
82 
83   // Now that the list of policy implementations, and the order to consult them,
84   // as been setup, do that.  If none of the policies make a definitive
85   // decisions about whether or not to check for updates, then allow the update
86   // check to happen.
87   EvalStatus status = ConsultPolicies(policies_to_consult,
88                                       &Policy::UpdateCheckAllowed,
89                                       ec,
90                                       state,
91                                       error,
92                                       result);
93   if (status != EvalStatus::kContinue) {
94     return status;
95   } else {
96     // It is time to check for an update.
97     LOG(INFO) << "Allowing update check.";
98     return EvalStatus::kSucceeded;
99   }
100 }
101 
102 // Uses the |UpdateRestrictions| to determine if the download and apply can
103 // occur at this time.
104 EvalStatus AndroidThingsPolicy::UpdateCanBeApplied(
105     EvaluationContext* ec,
106     State* state,
107     string* error,
108     ErrorCode* result,
109     chromeos_update_engine::InstallPlan* install_plan) const {
110   // Build a list of policies to consult.  Note that each policy may modify the
111   // result structure, even if it signals kContinue.
112   ApiRestrictedDownloadsPolicyImpl api_restricted_downloads_policy;
113 
114   vector<Policy const*> policies_to_consult = {
115       // Do not apply the update if all updates are restricted by the API.
116       &api_restricted_downloads_policy,
117   };
118 
119   // Now that the list of policy implementations, and the order to consult them,
120   // as been setup, do that.  If none of the policies make a definitive
121   // decisions about whether or not to check for updates, then allow the update
122   // check to happen.
123   EvalStatus status = ConsultPolicies(policies_to_consult,
124                                       &Policy::UpdateCanBeApplied,
125                                       ec,
126                                       state,
127                                       error,
128                                       result,
129                                       install_plan);
130   if (EvalStatus::kContinue != status) {
131     return status;
132   } else {
133     // The update can proceed.
134     LOG(INFO) << "Allowing update to be applied.";
135     *result = ErrorCode::kSuccess;
136     return EvalStatus::kSucceeded;
137   }
138 }
139 
140 // Always returns |EvalStatus::kSucceeded|
141 EvalStatus AndroidThingsPolicy::UpdateCanStart(EvaluationContext* ec,
142                                                State* state,
143                                                string* error,
144                                                UpdateDownloadParams* result,
145                                                UpdateState update_state) const {
146   // Update is good to go.
147   result->update_can_start = true;
148   return EvalStatus::kSucceeded;
149 }
150 
151 // Always returns |EvalStatus::kSucceeded|
152 EvalStatus AndroidThingsPolicy::UpdateDownloadAllowed(EvaluationContext* ec,
153                                                       State* state,
154                                                       string* error,
155                                                       bool* result) const {
156   // By default, we allow updates.
157   *result = true;
158   return EvalStatus::kSucceeded;
159 }
160 
161 // P2P is always disabled.  Returns |result|==|false| and
162 // |EvalStatus::kSucceeded|
163 EvalStatus AndroidThingsPolicy::P2PEnabled(EvaluationContext* ec,
164                                            State* state,
165                                            string* error,
166                                            bool* result) const {
167   *result = false;
168   return EvalStatus::kSucceeded;
169 }
170 
171 // This will return immediately with |EvalStatus::kSucceeded| and set
172 // |result|==|false|
173 EvalStatus AndroidThingsPolicy::P2PEnabledChanged(EvaluationContext* ec,
174                                                   State* state,
175                                                   string* error,
176                                                   bool* result,
177                                                   bool prev_result) const {
178   *result = false;
179   return EvalStatus::kSucceeded;
180 }
181 
182 }  // namespace chromeos_update_manager
183