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