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/aosp/binder_service_android.h"
18
19 #include <memory>
20
21 #include <base/bind.h>
22 #include <base/logging.h>
23 #include <binderwrapper/binder_wrapper.h>
24 #include <brillo/errors/error.h>
25 #include <utils/String8.h>
26
27 #include "update_engine/aosp/binder_service_android_common.h"
28
29 using android::binder::Status;
30 using android::os::IUpdateEngineCallback;
31 using android::os::ParcelFileDescriptor;
32 using std::string;
33 using std::vector;
34 using update_engine::UpdateEngineStatus;
35
36 namespace chromeos_update_engine {
37
BinderUpdateEngineAndroidService(ServiceDelegateAndroidInterface * service_delegate)38 BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
39 ServiceDelegateAndroidInterface* service_delegate)
40 : service_delegate_(service_delegate) {}
41
SendStatusUpdate(const UpdateEngineStatus & update_engine_status)42 void BinderUpdateEngineAndroidService::SendStatusUpdate(
43 const UpdateEngineStatus& update_engine_status) {
44 last_status_ = static_cast<int>(update_engine_status.status);
45 last_progress_ = update_engine_status.progress;
46 for (auto& callback : callbacks_) {
47 callback->onStatusUpdate(last_status_, last_progress_);
48 }
49 }
50
SendPayloadApplicationComplete(ErrorCode error_code)51 void BinderUpdateEngineAndroidService::SendPayloadApplicationComplete(
52 ErrorCode error_code) {
53 for (auto& callback : callbacks_) {
54 callback->onPayloadApplicationComplete(static_cast<int>(error_code));
55 }
56 }
57
bind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)58 Status BinderUpdateEngineAndroidService::bind(
59 const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
60 // Send an status update on connection (except when no update sent so far).
61 // Even though the status update is oneway, it still returns an erroneous
62 // status in case of a selinux denial. We should at least check this status
63 // and fails the binding.
64 if (last_status_ != -1) {
65 auto status = callback->onStatusUpdate(last_status_, last_progress_);
66 if (!status.isOk()) {
67 LOG(ERROR) << "Failed to call onStatusUpdate() from callback: "
68 << status.toString8();
69 *return_value = false;
70 return Status::ok();
71 }
72 }
73
74 callbacks_.emplace_back(callback);
75
76 const android::sp<IBinder>& callback_binder =
77 IUpdateEngineCallback::asBinder(callback);
78 auto binder_wrapper = android::BinderWrapper::Get();
79 binder_wrapper->RegisterForDeathNotifications(
80 callback_binder,
81 base::Bind(
82 base::IgnoreResult(&BinderUpdateEngineAndroidService::UnbindCallback),
83 base::Unretained(this),
84 base::Unretained(callback_binder.get())));
85
86 *return_value = true;
87 return Status::ok();
88 }
89
unbind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)90 Status BinderUpdateEngineAndroidService::unbind(
91 const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
92 const android::sp<IBinder>& callback_binder =
93 IUpdateEngineCallback::asBinder(callback);
94 auto binder_wrapper = android::BinderWrapper::Get();
95 binder_wrapper->UnregisterForDeathNotifications(callback_binder);
96
97 *return_value = UnbindCallback(callback_binder.get());
98 return Status::ok();
99 }
100
applyPayload(const android::String16 & url,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)101 Status BinderUpdateEngineAndroidService::applyPayload(
102 const android::String16& url,
103 int64_t payload_offset,
104 int64_t payload_size,
105 const vector<android::String16>& header_kv_pairs) {
106 const string payload_url{android::String8{url}.string()};
107 vector<string> str_headers = ToVecString(header_kv_pairs);
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
applyPayloadFd(const ParcelFileDescriptor & pfd,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)117 Status BinderUpdateEngineAndroidService::applyPayloadFd(
118 const ParcelFileDescriptor& pfd,
119 int64_t payload_offset,
120 int64_t payload_size,
121 const vector<android::String16>& header_kv_pairs) {
122 vector<string> str_headers = ToVecString(header_kv_pairs);
123
124 brillo::ErrorPtr error;
125 if (!service_delegate_->ApplyPayload(
126 pfd.get(), payload_offset, payload_size, str_headers, &error)) {
127 return ErrorPtrToStatus(error);
128 }
129 return Status::ok();
130 }
131
suspend()132 Status BinderUpdateEngineAndroidService::suspend() {
133 brillo::ErrorPtr error;
134 if (!service_delegate_->SuspendUpdate(&error))
135 return ErrorPtrToStatus(error);
136 return Status::ok();
137 }
138
resume()139 Status BinderUpdateEngineAndroidService::resume() {
140 brillo::ErrorPtr error;
141 if (!service_delegate_->ResumeUpdate(&error))
142 return ErrorPtrToStatus(error);
143 return Status::ok();
144 }
145
cancel()146 Status BinderUpdateEngineAndroidService::cancel() {
147 brillo::ErrorPtr error;
148 if (!service_delegate_->CancelUpdate(&error))
149 return ErrorPtrToStatus(error);
150 return Status::ok();
151 }
152
resetStatus()153 Status BinderUpdateEngineAndroidService::resetStatus() {
154 brillo::ErrorPtr error;
155 if (!service_delegate_->ResetStatus(&error))
156 return ErrorPtrToStatus(error);
157 return Status::ok();
158 }
159
verifyPayloadApplicable(const android::String16 & metadata_filename,bool * return_value)160 Status BinderUpdateEngineAndroidService::verifyPayloadApplicable(
161 const android::String16& metadata_filename, bool* return_value) {
162 const std::string payload_metadata{
163 android::String8{metadata_filename}.string()};
164 LOG(INFO) << "Received a request of verifying payload metadata in "
165 << payload_metadata << ".";
166 brillo::ErrorPtr error;
167 *return_value =
168 service_delegate_->VerifyPayloadApplicable(payload_metadata, &error);
169 if (error != nullptr)
170 return ErrorPtrToStatus(error);
171 return Status::ok();
172 }
173
UnbindCallback(const IBinder * callback)174 bool BinderUpdateEngineAndroidService::UnbindCallback(const IBinder* callback) {
175 auto it = std::find_if(
176 callbacks_.begin(),
177 callbacks_.end(),
178 [&callback](const android::sp<IUpdateEngineCallback>& elem) {
179 return IUpdateEngineCallback::asBinder(elem).get() == callback;
180 });
181 if (it == callbacks_.end()) {
182 LOG(ERROR) << "Unable to unbind unknown callback.";
183 return false;
184 }
185 callbacks_.erase(it);
186 return true;
187 }
188
allocateSpaceForPayload(const android::String16 & metadata_filename,const vector<android::String16> & header_kv_pairs,int64_t * return_value)189 Status BinderUpdateEngineAndroidService::allocateSpaceForPayload(
190 const android::String16& metadata_filename,
191 const vector<android::String16>& header_kv_pairs,
192 int64_t* return_value) {
193 const std::string payload_metadata{
194 android::String8{metadata_filename}.string()};
195 vector<string> str_headers = ToVecString(header_kv_pairs);
196 LOG(INFO) << "Received a request of allocating space for " << payload_metadata
197 << ".";
198 brillo::ErrorPtr error;
199 *return_value =
200 static_cast<int64_t>(service_delegate_->AllocateSpaceForPayload(
201 payload_metadata, str_headers, &error));
202 if (error != nullptr)
203 return ErrorPtrToStatus(error);
204 return Status::ok();
205 }
206
207 class CleanupSuccessfulUpdateCallback
208 : public CleanupSuccessfulUpdateCallbackInterface {
209 public:
CleanupSuccessfulUpdateCallback(const android::sp<IUpdateEngineCallback> & callback)210 CleanupSuccessfulUpdateCallback(
211 const android::sp<IUpdateEngineCallback>& callback)
212 : callback_(callback) {}
OnCleanupComplete(int32_t error_code)213 void OnCleanupComplete(int32_t error_code) {
214 ignore_result(callback_->onPayloadApplicationComplete(error_code));
215 }
OnCleanupProgressUpdate(double progress)216 void OnCleanupProgressUpdate(double progress) {
217 ignore_result(callback_->onStatusUpdate(
218 static_cast<int32_t>(
219 update_engine::UpdateStatus::CLEANUP_PREVIOUS_UPDATE),
220 progress));
221 }
RegisterForDeathNotifications(base::Closure unbind)222 void RegisterForDeathNotifications(base::Closure unbind) {
223 const android::sp<android::IBinder>& callback_binder =
224 IUpdateEngineCallback::asBinder(callback_);
225 auto binder_wrapper = android::BinderWrapper::Get();
226 binder_wrapper->RegisterForDeathNotifications(callback_binder, unbind);
227 }
228
229 private:
230 android::sp<IUpdateEngineCallback> callback_;
231 };
232
cleanupSuccessfulUpdate(const android::sp<IUpdateEngineCallback> & callback)233 Status BinderUpdateEngineAndroidService::cleanupSuccessfulUpdate(
234 const android::sp<IUpdateEngineCallback>& callback) {
235 brillo::ErrorPtr error;
236 service_delegate_->CleanupSuccessfulUpdate(
237 std::make_unique<CleanupSuccessfulUpdateCallback>(callback), &error);
238 if (error != nullptr)
239 return ErrorPtrToStatus(error);
240 return Status::ok();
241 }
242
243 } // namespace chromeos_update_engine
244