• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/binder_service_android.h"
18 
19 #include <base/bind.h>
20 #include <base/logging.h>
21 #include <binderwrapper/binder_wrapper.h>
22 #include <brillo/errors/error.h>
23 #include <utils/String8.h>
24 
25 using android::binder::Status;
26 using android::os::IUpdateEngineCallback;
27 
28 namespace {
ErrorPtrToStatus(const brillo::ErrorPtr & error)29 Status ErrorPtrToStatus(const brillo::ErrorPtr& error) {
30   return Status::fromServiceSpecificError(
31       1, android::String8{error->GetMessage().c_str()});
32 }
33 }  // namespace
34 
35 namespace chromeos_update_engine {
36 
BinderUpdateEngineAndroidService(ServiceDelegateAndroidInterface * service_delegate)37 BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
38     ServiceDelegateAndroidInterface* service_delegate)
39     : service_delegate_(service_delegate) {
40 }
41 
SendStatusUpdate(int64_t,double progress,update_engine::UpdateStatus status,const std::string &,int64_t)42 void BinderUpdateEngineAndroidService::SendStatusUpdate(
43     int64_t /* last_checked_time */,
44     double progress,
45     update_engine::UpdateStatus status,
46     const std::string& /* new_version  */,
47     int64_t /* new_size */) {
48   last_status_ = static_cast<int>(status);
49   last_progress_ = progress;
50   for (auto& callback : callbacks_) {
51     callback->onStatusUpdate(last_status_, last_progress_);
52   }
53 }
54 
SendPayloadApplicationComplete(ErrorCode error_code)55 void BinderUpdateEngineAndroidService::SendPayloadApplicationComplete(
56     ErrorCode error_code) {
57   for (auto& callback : callbacks_) {
58     callback->onPayloadApplicationComplete(static_cast<int>(error_code));
59   }
60 }
61 
bind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)62 Status BinderUpdateEngineAndroidService::bind(
63     const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
64   callbacks_.emplace_back(callback);
65 
66   const android::sp<IBinder>& callback_binder =
67       IUpdateEngineCallback::asBinder(callback);
68   auto binder_wrapper = android::BinderWrapper::Get();
69   binder_wrapper->RegisterForDeathNotifications(
70       callback_binder,
71       base::Bind(
72           base::IgnoreResult(&BinderUpdateEngineAndroidService::UnbindCallback),
73           base::Unretained(this),
74           base::Unretained(callback_binder.get())));
75 
76   // Send an status update on connection (except when no update sent so far),
77   // since the status update is oneway and we don't need to wait for the
78   // response.
79   if (last_status_ != -1)
80     callback->onStatusUpdate(last_status_, last_progress_);
81 
82   *return_value = true;
83   return Status::ok();
84 }
85 
unbind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)86 Status BinderUpdateEngineAndroidService::unbind(
87     const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
88   const android::sp<IBinder>& callback_binder =
89       IUpdateEngineCallback::asBinder(callback);
90   auto binder_wrapper = android::BinderWrapper::Get();
91   binder_wrapper->UnregisterForDeathNotifications(callback_binder);
92 
93   *return_value = UnbindCallback(callback_binder.get());
94   return Status::ok();
95 }
96 
applyPayload(const android::String16 & url,int64_t payload_offset,int64_t payload_size,const std::vector<android::String16> & header_kv_pairs)97 Status BinderUpdateEngineAndroidService::applyPayload(
98     const android::String16& url,
99     int64_t payload_offset,
100     int64_t payload_size,
101     const std::vector<android::String16>& header_kv_pairs) {
102   const std::string payload_url{android::String8{url}.string()};
103   std::vector<std::string> str_headers;
104   str_headers.reserve(header_kv_pairs.size());
105   for (const auto& header : header_kv_pairs) {
106     str_headers.emplace_back(android::String8{header}.string());
107   }
108 
109   brillo::ErrorPtr error;
110   if (!service_delegate_->ApplyPayload(
111           payload_url, payload_offset, payload_size, str_headers, &error)) {
112     return ErrorPtrToStatus(error);
113   }
114   return Status::ok();
115 }
116 
suspend()117 Status BinderUpdateEngineAndroidService::suspend() {
118   brillo::ErrorPtr error;
119   if (!service_delegate_->SuspendUpdate(&error))
120     return ErrorPtrToStatus(error);
121   return Status::ok();
122 }
123 
resume()124 Status BinderUpdateEngineAndroidService::resume() {
125   brillo::ErrorPtr error;
126   if (!service_delegate_->ResumeUpdate(&error))
127     return ErrorPtrToStatus(error);
128   return Status::ok();
129 }
130 
cancel()131 Status BinderUpdateEngineAndroidService::cancel() {
132   brillo::ErrorPtr error;
133   if (!service_delegate_->CancelUpdate(&error))
134     return ErrorPtrToStatus(error);
135   return Status::ok();
136 }
137 
resetStatus()138 Status BinderUpdateEngineAndroidService::resetStatus() {
139   brillo::ErrorPtr error;
140   if (!service_delegate_->ResetStatus(&error))
141     return ErrorPtrToStatus(error);
142   return Status::ok();
143 }
144 
UnbindCallback(const IBinder * callback)145 bool BinderUpdateEngineAndroidService::UnbindCallback(const IBinder* callback) {
146   auto it = std::find_if(
147       callbacks_.begin(),
148       callbacks_.end(),
149       [&callback](const android::sp<IUpdateEngineCallback>& elem) {
150         return IUpdateEngineCallback::asBinder(elem).get() == callback;
151       });
152   if (it == callbacks_.end()) {
153     LOG(ERROR) << "Unable to unbind unknown callback.";
154     return false;
155   }
156   callbacks_.erase(it);
157   return true;
158 }
159 
160 }  // namespace chromeos_update_engine
161