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