1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2015 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/binder_service_android.h"
18*5a923131SAndroid Build Coastguard Worker
19*5a923131SAndroid Build Coastguard Worker #include <memory>
20*5a923131SAndroid Build Coastguard Worker
21*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
22*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
23*5a923131SAndroid Build Coastguard Worker #include <binderwrapper/binder_wrapper.h>
24*5a923131SAndroid Build Coastguard Worker #include <utils/String8.h>
25*5a923131SAndroid Build Coastguard Worker
26*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/binder_service_android_common.h"
27*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/error_code.h"
28*5a923131SAndroid Build Coastguard Worker
29*5a923131SAndroid Build Coastguard Worker using android::binder::Status;
30*5a923131SAndroid Build Coastguard Worker using android::os::IUpdateEngineCallback;
31*5a923131SAndroid Build Coastguard Worker using android::os::ParcelFileDescriptor;
32*5a923131SAndroid Build Coastguard Worker using std::string;
33*5a923131SAndroid Build Coastguard Worker using std::vector;
34*5a923131SAndroid Build Coastguard Worker using update_engine::UpdateEngineStatus;
35*5a923131SAndroid Build Coastguard Worker
36*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
37*5a923131SAndroid Build Coastguard Worker
BinderUpdateEngineAndroidService(ServiceDelegateAndroidInterface * service_delegate)38*5a923131SAndroid Build Coastguard Worker BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
39*5a923131SAndroid Build Coastguard Worker ServiceDelegateAndroidInterface* service_delegate)
40*5a923131SAndroid Build Coastguard Worker : service_delegate_(service_delegate) {}
41*5a923131SAndroid Build Coastguard Worker
SendStatusUpdate(const UpdateEngineStatus & update_engine_status)42*5a923131SAndroid Build Coastguard Worker void BinderUpdateEngineAndroidService::SendStatusUpdate(
43*5a923131SAndroid Build Coastguard Worker const UpdateEngineStatus& update_engine_status) {
44*5a923131SAndroid Build Coastguard Worker last_status_ = static_cast<int>(update_engine_status.status);
45*5a923131SAndroid Build Coastguard Worker last_progress_ = update_engine_status.progress;
46*5a923131SAndroid Build Coastguard Worker for (auto& callback : callbacks_) {
47*5a923131SAndroid Build Coastguard Worker callback->onStatusUpdate(last_status_, last_progress_);
48*5a923131SAndroid Build Coastguard Worker }
49*5a923131SAndroid Build Coastguard Worker }
50*5a923131SAndroid Build Coastguard Worker
SendPayloadApplicationComplete(ErrorCode error_code)51*5a923131SAndroid Build Coastguard Worker void BinderUpdateEngineAndroidService::SendPayloadApplicationComplete(
52*5a923131SAndroid Build Coastguard Worker ErrorCode error_code) {
53*5a923131SAndroid Build Coastguard Worker for (auto& callback : callbacks_) {
54*5a923131SAndroid Build Coastguard Worker callback->onPayloadApplicationComplete(static_cast<int>(error_code));
55*5a923131SAndroid Build Coastguard Worker }
56*5a923131SAndroid Build Coastguard Worker }
57*5a923131SAndroid Build Coastguard Worker
bind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)58*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::bind(
59*5a923131SAndroid Build Coastguard Worker const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
60*5a923131SAndroid Build Coastguard Worker // Send an status update on connection (except when no update sent so far).
61*5a923131SAndroid Build Coastguard Worker // Even though the status update is oneway, it still returns an erroneous
62*5a923131SAndroid Build Coastguard Worker // status in case of a selinux denial. We should at least check this status
63*5a923131SAndroid Build Coastguard Worker // and fails the binding.
64*5a923131SAndroid Build Coastguard Worker if (last_status_ != -1) {
65*5a923131SAndroid Build Coastguard Worker auto status = callback->onStatusUpdate(last_status_, last_progress_);
66*5a923131SAndroid Build Coastguard Worker if (!status.isOk()) {
67*5a923131SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to call onStatusUpdate() from callback: "
68*5a923131SAndroid Build Coastguard Worker << status.toString8();
69*5a923131SAndroid Build Coastguard Worker *return_value = false;
70*5a923131SAndroid Build Coastguard Worker return Status::ok();
71*5a923131SAndroid Build Coastguard Worker }
72*5a923131SAndroid Build Coastguard Worker }
73*5a923131SAndroid Build Coastguard Worker
74*5a923131SAndroid Build Coastguard Worker callbacks_.emplace_back(callback);
75*5a923131SAndroid Build Coastguard Worker
76*5a923131SAndroid Build Coastguard Worker const android::sp<IBinder>& callback_binder =
77*5a923131SAndroid Build Coastguard Worker IUpdateEngineCallback::asBinder(callback);
78*5a923131SAndroid Build Coastguard Worker auto binder_wrapper = android::BinderWrapper::Get();
79*5a923131SAndroid Build Coastguard Worker binder_wrapper->RegisterForDeathNotifications(
80*5a923131SAndroid Build Coastguard Worker callback_binder,
81*5a923131SAndroid Build Coastguard Worker [this, callback = callback_binder.get()]() { UnbindCallback(callback); });
82*5a923131SAndroid Build Coastguard Worker
83*5a923131SAndroid Build Coastguard Worker *return_value = true;
84*5a923131SAndroid Build Coastguard Worker return Status::ok();
85*5a923131SAndroid Build Coastguard Worker }
86*5a923131SAndroid Build Coastguard Worker
unbind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)87*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::unbind(
88*5a923131SAndroid Build Coastguard Worker const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
89*5a923131SAndroid Build Coastguard Worker const android::sp<IBinder>& callback_binder =
90*5a923131SAndroid Build Coastguard Worker IUpdateEngineCallback::asBinder(callback);
91*5a923131SAndroid Build Coastguard Worker auto binder_wrapper = android::BinderWrapper::Get();
92*5a923131SAndroid Build Coastguard Worker binder_wrapper->UnregisterForDeathNotifications(callback_binder);
93*5a923131SAndroid Build Coastguard Worker
94*5a923131SAndroid Build Coastguard Worker *return_value = UnbindCallback(callback_binder.get());
95*5a923131SAndroid Build Coastguard Worker return Status::ok();
96*5a923131SAndroid Build Coastguard Worker }
97*5a923131SAndroid Build Coastguard Worker
applyPayload(const android::String16 & url,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)98*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::applyPayload(
99*5a923131SAndroid Build Coastguard Worker const android::String16& url,
100*5a923131SAndroid Build Coastguard Worker int64_t payload_offset,
101*5a923131SAndroid Build Coastguard Worker int64_t payload_size,
102*5a923131SAndroid Build Coastguard Worker const vector<android::String16>& header_kv_pairs) {
103*5a923131SAndroid Build Coastguard Worker const string payload_url{android::String8{url}.c_str()};
104*5a923131SAndroid Build Coastguard Worker vector<string> str_headers = ToVecString(header_kv_pairs);
105*5a923131SAndroid Build Coastguard Worker
106*5a923131SAndroid Build Coastguard Worker Error error;
107*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->ApplyPayload(
108*5a923131SAndroid Build Coastguard Worker payload_url, payload_offset, payload_size, str_headers, &error)) {
109*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
110*5a923131SAndroid Build Coastguard Worker }
111*5a923131SAndroid Build Coastguard Worker return Status::ok();
112*5a923131SAndroid Build Coastguard Worker }
113*5a923131SAndroid Build Coastguard Worker
applyPayloadFd(const ParcelFileDescriptor & pfd,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)114*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::applyPayloadFd(
115*5a923131SAndroid Build Coastguard Worker const ParcelFileDescriptor& pfd,
116*5a923131SAndroid Build Coastguard Worker int64_t payload_offset,
117*5a923131SAndroid Build Coastguard Worker int64_t payload_size,
118*5a923131SAndroid Build Coastguard Worker const vector<android::String16>& header_kv_pairs) {
119*5a923131SAndroid Build Coastguard Worker vector<string> str_headers = ToVecString(header_kv_pairs);
120*5a923131SAndroid Build Coastguard Worker
121*5a923131SAndroid Build Coastguard Worker Error error;
122*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->ApplyPayload(
123*5a923131SAndroid Build Coastguard Worker pfd.get(), payload_offset, payload_size, str_headers, &error)) {
124*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
125*5a923131SAndroid Build Coastguard Worker }
126*5a923131SAndroid Build Coastguard Worker return Status::ok();
127*5a923131SAndroid Build Coastguard Worker }
128*5a923131SAndroid Build Coastguard Worker
suspend()129*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::suspend() {
130*5a923131SAndroid Build Coastguard Worker Error error;
131*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->SuspendUpdate(&error))
132*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
133*5a923131SAndroid Build Coastguard Worker return Status::ok();
134*5a923131SAndroid Build Coastguard Worker }
135*5a923131SAndroid Build Coastguard Worker
resume()136*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::resume() {
137*5a923131SAndroid Build Coastguard Worker Error error;
138*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->ResumeUpdate(&error))
139*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
140*5a923131SAndroid Build Coastguard Worker return Status::ok();
141*5a923131SAndroid Build Coastguard Worker }
142*5a923131SAndroid Build Coastguard Worker
cancel()143*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::cancel() {
144*5a923131SAndroid Build Coastguard Worker Error error;
145*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->CancelUpdate(&error))
146*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
147*5a923131SAndroid Build Coastguard Worker return Status::ok();
148*5a923131SAndroid Build Coastguard Worker }
149*5a923131SAndroid Build Coastguard Worker
resetStatus()150*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::resetStatus() {
151*5a923131SAndroid Build Coastguard Worker Error error;
152*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->ResetStatus(&error))
153*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
154*5a923131SAndroid Build Coastguard Worker return Status::ok();
155*5a923131SAndroid Build Coastguard Worker }
156*5a923131SAndroid Build Coastguard Worker
setShouldSwitchSlotOnReboot(const android::String16 & metadata_filename)157*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::setShouldSwitchSlotOnReboot(
158*5a923131SAndroid Build Coastguard Worker const android::String16& metadata_filename) {
159*5a923131SAndroid Build Coastguard Worker Error error;
160*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->setShouldSwitchSlotOnReboot(
161*5a923131SAndroid Build Coastguard Worker android::String8(metadata_filename).c_str(), &error)) {
162*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
163*5a923131SAndroid Build Coastguard Worker }
164*5a923131SAndroid Build Coastguard Worker return Status::ok();
165*5a923131SAndroid Build Coastguard Worker }
166*5a923131SAndroid Build Coastguard Worker
resetShouldSwitchSlotOnReboot()167*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::resetShouldSwitchSlotOnReboot() {
168*5a923131SAndroid Build Coastguard Worker Error error;
169*5a923131SAndroid Build Coastguard Worker if (!service_delegate_->resetShouldSwitchSlotOnReboot(&error)) {
170*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
171*5a923131SAndroid Build Coastguard Worker }
172*5a923131SAndroid Build Coastguard Worker return Status::ok();
173*5a923131SAndroid Build Coastguard Worker }
174*5a923131SAndroid Build Coastguard Worker
verifyPayloadApplicable(const android::String16 & metadata_filename,bool * return_value)175*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::verifyPayloadApplicable(
176*5a923131SAndroid Build Coastguard Worker const android::String16& metadata_filename, bool* return_value) {
177*5a923131SAndroid Build Coastguard Worker const std::string payload_metadata{
178*5a923131SAndroid Build Coastguard Worker android::String8{metadata_filename}.c_str()};
179*5a923131SAndroid Build Coastguard Worker LOG(INFO) << "Received a request of verifying payload metadata in "
180*5a923131SAndroid Build Coastguard Worker << payload_metadata << ".";
181*5a923131SAndroid Build Coastguard Worker Error error;
182*5a923131SAndroid Build Coastguard Worker *return_value =
183*5a923131SAndroid Build Coastguard Worker service_delegate_->VerifyPayloadApplicable(payload_metadata, &error);
184*5a923131SAndroid Build Coastguard Worker if (error.error_code != ErrorCode::kSuccess)
185*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
186*5a923131SAndroid Build Coastguard Worker return Status::ok();
187*5a923131SAndroid Build Coastguard Worker }
188*5a923131SAndroid Build Coastguard Worker
UnbindCallback(const IBinder * callback)189*5a923131SAndroid Build Coastguard Worker bool BinderUpdateEngineAndroidService::UnbindCallback(const IBinder* callback) {
190*5a923131SAndroid Build Coastguard Worker auto it = std::find_if(
191*5a923131SAndroid Build Coastguard Worker callbacks_.begin(),
192*5a923131SAndroid Build Coastguard Worker callbacks_.end(),
193*5a923131SAndroid Build Coastguard Worker [&callback](const android::sp<IUpdateEngineCallback>& elem) {
194*5a923131SAndroid Build Coastguard Worker return IUpdateEngineCallback::asBinder(elem).get() == callback;
195*5a923131SAndroid Build Coastguard Worker });
196*5a923131SAndroid Build Coastguard Worker if (it == callbacks_.end()) {
197*5a923131SAndroid Build Coastguard Worker LOG(ERROR) << "Unable to unbind unknown callback.";
198*5a923131SAndroid Build Coastguard Worker return false;
199*5a923131SAndroid Build Coastguard Worker }
200*5a923131SAndroid Build Coastguard Worker callbacks_.erase(it);
201*5a923131SAndroid Build Coastguard Worker return true;
202*5a923131SAndroid Build Coastguard Worker }
203*5a923131SAndroid Build Coastguard Worker
allocateSpaceForPayload(const android::String16 & metadata_filename,const vector<android::String16> & header_kv_pairs,int64_t * return_value)204*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::allocateSpaceForPayload(
205*5a923131SAndroid Build Coastguard Worker const android::String16& metadata_filename,
206*5a923131SAndroid Build Coastguard Worker const vector<android::String16>& header_kv_pairs,
207*5a923131SAndroid Build Coastguard Worker int64_t* return_value) {
208*5a923131SAndroid Build Coastguard Worker const std::string payload_metadata{
209*5a923131SAndroid Build Coastguard Worker android::String8{metadata_filename}.c_str()};
210*5a923131SAndroid Build Coastguard Worker vector<string> str_headers = ToVecString(header_kv_pairs);
211*5a923131SAndroid Build Coastguard Worker LOG(INFO) << "Received a request of allocating space for " << payload_metadata
212*5a923131SAndroid Build Coastguard Worker << ".";
213*5a923131SAndroid Build Coastguard Worker Error error;
214*5a923131SAndroid Build Coastguard Worker *return_value =
215*5a923131SAndroid Build Coastguard Worker static_cast<int64_t>(service_delegate_->AllocateSpaceForPayload(
216*5a923131SAndroid Build Coastguard Worker payload_metadata, str_headers, &error));
217*5a923131SAndroid Build Coastguard Worker if (error.error_code != ErrorCode::kSuccess)
218*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
219*5a923131SAndroid Build Coastguard Worker return Status::ok();
220*5a923131SAndroid Build Coastguard Worker }
221*5a923131SAndroid Build Coastguard Worker
222*5a923131SAndroid Build Coastguard Worker class CleanupSuccessfulUpdateCallback
223*5a923131SAndroid Build Coastguard Worker : public CleanupSuccessfulUpdateCallbackInterface {
224*5a923131SAndroid Build Coastguard Worker public:
CleanupSuccessfulUpdateCallback(const android::sp<IUpdateEngineCallback> & callback)225*5a923131SAndroid Build Coastguard Worker CleanupSuccessfulUpdateCallback(
226*5a923131SAndroid Build Coastguard Worker const android::sp<IUpdateEngineCallback>& callback)
227*5a923131SAndroid Build Coastguard Worker : callback_(callback) {}
OnCleanupComplete(int32_t error_code)228*5a923131SAndroid Build Coastguard Worker void OnCleanupComplete(int32_t error_code) {
229*5a923131SAndroid Build Coastguard Worker ignore_result(callback_->onPayloadApplicationComplete(error_code));
230*5a923131SAndroid Build Coastguard Worker }
OnCleanupProgressUpdate(double progress)231*5a923131SAndroid Build Coastguard Worker void OnCleanupProgressUpdate(double progress) {
232*5a923131SAndroid Build Coastguard Worker ignore_result(callback_->onStatusUpdate(
233*5a923131SAndroid Build Coastguard Worker static_cast<int32_t>(
234*5a923131SAndroid Build Coastguard Worker update_engine::UpdateStatus::CLEANUP_PREVIOUS_UPDATE),
235*5a923131SAndroid Build Coastguard Worker progress));
236*5a923131SAndroid Build Coastguard Worker }
RegisterForDeathNotifications(const std::function<void ()> & unbind)237*5a923131SAndroid Build Coastguard Worker void RegisterForDeathNotifications(const std::function<void()>& unbind) {
238*5a923131SAndroid Build Coastguard Worker const android::sp<android::IBinder>& callback_binder =
239*5a923131SAndroid Build Coastguard Worker IUpdateEngineCallback::asBinder(callback_);
240*5a923131SAndroid Build Coastguard Worker auto binder_wrapper = android::BinderWrapper::Get();
241*5a923131SAndroid Build Coastguard Worker binder_wrapper->RegisterForDeathNotifications(callback_binder, unbind);
242*5a923131SAndroid Build Coastguard Worker }
243*5a923131SAndroid Build Coastguard Worker
244*5a923131SAndroid Build Coastguard Worker private:
245*5a923131SAndroid Build Coastguard Worker android::sp<IUpdateEngineCallback> callback_;
246*5a923131SAndroid Build Coastguard Worker };
247*5a923131SAndroid Build Coastguard Worker
cleanupSuccessfulUpdate(const android::sp<IUpdateEngineCallback> & callback)248*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::cleanupSuccessfulUpdate(
249*5a923131SAndroid Build Coastguard Worker const android::sp<IUpdateEngineCallback>& callback) {
250*5a923131SAndroid Build Coastguard Worker Error error;
251*5a923131SAndroid Build Coastguard Worker service_delegate_->CleanupSuccessfulUpdate(
252*5a923131SAndroid Build Coastguard Worker std::make_unique<CleanupSuccessfulUpdateCallback>(callback), &error);
253*5a923131SAndroid Build Coastguard Worker if (error.error_code != ErrorCode::kSuccess)
254*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
255*5a923131SAndroid Build Coastguard Worker return Status::ok();
256*5a923131SAndroid Build Coastguard Worker }
257*5a923131SAndroid Build Coastguard Worker
triggerPostinstall(const::android::String16 & partition)258*5a923131SAndroid Build Coastguard Worker Status BinderUpdateEngineAndroidService::triggerPostinstall(
259*5a923131SAndroid Build Coastguard Worker const ::android::String16& partition) {
260*5a923131SAndroid Build Coastguard Worker Error error;
261*5a923131SAndroid Build Coastguard Worker service_delegate_->TriggerPostinstall(android::String8(partition).c_str(),
262*5a923131SAndroid Build Coastguard Worker &error);
263*5a923131SAndroid Build Coastguard Worker if (error.error_code != ErrorCode::kSuccess)
264*5a923131SAndroid Build Coastguard Worker return ErrorPtrToStatus(error);
265*5a923131SAndroid Build Coastguard Worker return Status::ok();
266*5a923131SAndroid Build Coastguard Worker }
267*5a923131SAndroid Build Coastguard Worker
268*5a923131SAndroid Build Coastguard Worker } // namespace chromeos_update_engine
269