1 //
2 // Copyright (C) 2015 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/client_library/client_binder.h"
18 
19 #include <binder/IServiceManager.h>
20 
21 #include <base/message_loop/message_loop.h>
22 #include <utils/String8.h>
23 
24 #include "update_engine/common_service.h"
25 #include "update_engine/parcelable_update_engine_status.h"
26 #include "update_engine/update_status_utils.h"
27 
28 using android::getService;
29 using android::OK;
30 using android::String16;
31 using android::String8;
32 using android::binder::Status;
33 using android::brillo::ParcelableUpdateEngineStatus;
34 using chromeos_update_engine::StringToUpdateStatus;
35 using std::string;
36 using update_engine::UpdateAttemptFlags;
37 
38 namespace update_engine {
39 namespace internal {
40 
41 bool BinderUpdateEngineClient::Init() {
42   if (!binder_watcher_.Init())
43     return false;
44 
45   return getService(String16{"android.brillo.UpdateEngineService"},
46                     &service_) == OK;
47 }
48 
49 bool BinderUpdateEngineClient::AttemptUpdate(const string& in_app_version,
50                                              const string& in_omaha_url,
51                                              bool at_user_request) {
52   bool started;
53   return service_
54       ->AttemptUpdate(
55           String16{in_app_version.c_str()},
56           String16{in_omaha_url.c_str()},
57           at_user_request ? 0 : UpdateAttemptFlags::kFlagNonInteractive,
58           &started)
59       .isOk();
60 }
61 
62 bool BinderUpdateEngineClient::AttemptInstall(
63     const string& omaha_url, const std::vector<string>& dlc_module_ids) {
64   return false;
65 }
66 
67 bool BinderUpdateEngineClient::GetStatus(int64_t* out_last_checked_time,
68                                          double* out_progress,
69                                          UpdateStatus* out_update_status,
70                                          string* out_new_version,
71                                          int64_t* out_new_size) const {
72   ParcelableUpdateEngineStatus status;
73 
74   if (!service_->GetStatus(&status).isOk())
75     return false;
76 
77   *out_last_checked_time = status.last_checked_time_;
78   *out_progress = status.progress_;
79   StringToUpdateStatus(String8{status.current_operation_}.string(),
80                        out_update_status);
81   *out_new_version = String8{status.new_version_}.string();
82   *out_new_size = status.new_size_;
83   return true;
84 }
85 
86 bool BinderUpdateEngineClient::SetCohortHint(const string& in_cohort_hint) {
87   return service_->SetCohortHint(String16{in_cohort_hint.c_str()}).isOk();
88 }
89 
90 bool BinderUpdateEngineClient::GetCohortHint(string* out_cohort_hint) const {
91   String16 out_as_string16;
92 
93   if (!service_->GetCohortHint(&out_as_string16).isOk())
94     return false;
95 
96   *out_cohort_hint = String8{out_as_string16}.string();
97   return true;
98 }
99 
100 bool BinderUpdateEngineClient::SetUpdateOverCellularPermission(bool allowed) {
101   return service_->SetUpdateOverCellularPermission(allowed).isOk();
102 }
103 
104 bool BinderUpdateEngineClient::GetUpdateOverCellularPermission(
105     bool* allowed) const {
106   return service_->GetUpdateOverCellularPermission(allowed).isOk();
107 }
108 
109 bool BinderUpdateEngineClient::SetP2PUpdatePermission(bool enabled) {
110   return service_->SetP2PUpdatePermission(enabled).isOk();
111 }
112 
113 bool BinderUpdateEngineClient::GetP2PUpdatePermission(bool* enabled) const {
114   return service_->GetP2PUpdatePermission(enabled).isOk();
115 }
116 
117 bool BinderUpdateEngineClient::Rollback(bool powerwash) {
118   return service_->AttemptRollback(powerwash).isOk();
119 }
120 
121 bool BinderUpdateEngineClient::GetRollbackPartition(
122     string* rollback_partition) const {
123   String16 out_as_string16;
124 
125   if (!service_->GetRollbackPartition(&out_as_string16).isOk())
126     return false;
127 
128   *rollback_partition = String8{out_as_string16}.string();
129   return true;
130 }
131 
132 bool BinderUpdateEngineClient::GetPrevVersion(string* prev_version) const {
133   String16 out_as_string16;
134 
135   if (!service_->GetPrevVersion(&out_as_string16).isOk())
136     return false;
137 
138   *prev_version = String8{out_as_string16}.string();
139   return true;
140 }
141 
142 void BinderUpdateEngineClient::RebootIfNeeded() {
143   if (!service_->RebootIfNeeded().isOk()) {
144     // Reboot error code doesn't necessarily mean that a reboot
145     // failed. For example, D-Bus may be shutdown before we receive the
146     // result.
147     LOG(INFO) << "RebootIfNeeded() failure ignored.";
148   }
149 }
150 
151 bool BinderUpdateEngineClient::ResetStatus() {
152   return service_->ResetStatus().isOk();
153 }
154 
155 Status BinderUpdateEngineClient::StatusUpdateCallback::HandleStatusUpdate(
156     const ParcelableUpdateEngineStatus& status) {
157   UpdateStatus update_status;
158 
159   StringToUpdateStatus(String8{status.current_operation_}.string(),
160                        &update_status);
161 
162   for (auto& handler : client_->handlers_) {
163     handler->HandleStatusUpdate(status.last_checked_time_,
164                                 status.progress_,
165                                 update_status,
166                                 String8{status.new_version_}.string(),
167                                 status.new_size_);
168   }
169 
170   return Status::ok();
171 }
172 
173 bool BinderUpdateEngineClient::RegisterStatusUpdateHandler(
174     StatusUpdateHandler* handler) {
175   if (!status_callback_.get()) {
176     status_callback_ = new BinderUpdateEngineClient::StatusUpdateCallback(this);
177     if (!service_->RegisterStatusCallback(status_callback_).isOk()) {
178       return false;
179     }
180   }
181 
182   handlers_.push_back(handler);
183 
184   int64_t last_checked_time;
185   double progress;
186   UpdateStatus update_status;
187   string new_version;
188   int64_t new_size;
189 
190   if (!GetStatus(&last_checked_time,
191                  &progress,
192                  &update_status,
193                  &new_version,
194                  &new_size)) {
195     handler->IPCError("Could not get status from binder service");
196   }
197 
198   handler->HandleStatusUpdate(
199       last_checked_time, progress, update_status, new_version, new_size);
200 
201   return true;
202 }
203 
204 bool BinderUpdateEngineClient::UnregisterStatusUpdateHandler(
205     StatusUpdateHandler* handler) {
206   auto it = std::find(handlers_.begin(), handlers_.end(), handler);
207   if (it != handlers_.end()) {
208     handlers_.erase(it);
209     return true;
210   }
211 
212   return false;
213 }
214 
215 bool BinderUpdateEngineClient::SetTargetChannel(const string& in_target_channel,
216                                                 bool allow_powerwash) {
217   return service_
218       ->SetChannel(String16{in_target_channel.c_str()}, allow_powerwash)
219       .isOk();
220 }
221 
222 bool BinderUpdateEngineClient::GetTargetChannel(string* out_channel) const {
223   String16 out_as_string16;
224 
225   if (!service_->GetChannel(false, &out_as_string16).isOk())
226     return false;
227 
228   *out_channel = String8{out_as_string16}.string();
229   return true;
230 }
231 
232 bool BinderUpdateEngineClient::GetChannel(string* out_channel) const {
233   String16 out_as_string16;
234 
235   if (!service_->GetChannel(true, &out_as_string16).isOk())
236     return false;
237 
238   *out_channel = String8{out_as_string16}.string();
239   return true;
240 }
241 
242 bool BinderUpdateEngineClient::GetLastAttemptError(
243     int32_t* last_attempt_error) const {
244   int out_as_int;
245 
246   if (!service_->GetLastAttemptError(&out_as_int).isOk())
247     return false;
248 
249   *last_attempt_error = out_as_int;
250   return true;
251 }
252 
253 bool BinderUpdateEngineClient::GetEolStatus(int32_t* eol_status) const {
254   int out_as_int;
255 
256   if (!service_->GetEolStatus(&out_as_int).isOk())
257     return false;
258 
259   *eol_status = out_as_int;
260   return true;
261 }
262 
263 }  // namespace internal
264 }  // namespace update_engine
265