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