xref: /aosp_15_r20/system/update_engine/aosp/binder_service_android.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
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 #include "update_engine/common/error_code.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       [this, callback = callback_binder.get()]() { UnbindCallback(callback); });
82 
83   *return_value = true;
84   return Status::ok();
85 }
86 
unbind(const android::sp<IUpdateEngineCallback> & callback,bool * return_value)87 Status BinderUpdateEngineAndroidService::unbind(
88     const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
89   const android::sp<IBinder>& callback_binder =
90       IUpdateEngineCallback::asBinder(callback);
91   auto binder_wrapper = android::BinderWrapper::Get();
92   binder_wrapper->UnregisterForDeathNotifications(callback_binder);
93 
94   *return_value = UnbindCallback(callback_binder.get());
95   return Status::ok();
96 }
97 
applyPayload(const android::String16 & url,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)98 Status BinderUpdateEngineAndroidService::applyPayload(
99     const android::String16& url,
100     int64_t payload_offset,
101     int64_t payload_size,
102     const vector<android::String16>& header_kv_pairs) {
103   const string payload_url{android::String8{url}.c_str()};
104   vector<string> str_headers = ToVecString(header_kv_pairs);
105 
106   Error 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 
applyPayloadFd(const ParcelFileDescriptor & pfd,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)114 Status BinderUpdateEngineAndroidService::applyPayloadFd(
115     const ParcelFileDescriptor& pfd,
116     int64_t payload_offset,
117     int64_t payload_size,
118     const vector<android::String16>& header_kv_pairs) {
119   vector<string> str_headers = ToVecString(header_kv_pairs);
120 
121   Error error;
122   if (!service_delegate_->ApplyPayload(
123           pfd.get(), payload_offset, payload_size, str_headers, &error)) {
124     return ErrorPtrToStatus(error);
125   }
126   return Status::ok();
127 }
128 
suspend()129 Status BinderUpdateEngineAndroidService::suspend() {
130   Error error;
131   if (!service_delegate_->SuspendUpdate(&error))
132     return ErrorPtrToStatus(error);
133   return Status::ok();
134 }
135 
resume()136 Status BinderUpdateEngineAndroidService::resume() {
137   Error error;
138   if (!service_delegate_->ResumeUpdate(&error))
139     return ErrorPtrToStatus(error);
140   return Status::ok();
141 }
142 
cancel()143 Status BinderUpdateEngineAndroidService::cancel() {
144   Error error;
145   if (!service_delegate_->CancelUpdate(&error))
146     return ErrorPtrToStatus(error);
147   return Status::ok();
148 }
149 
resetStatus()150 Status BinderUpdateEngineAndroidService::resetStatus() {
151   Error error;
152   if (!service_delegate_->ResetStatus(&error))
153     return ErrorPtrToStatus(error);
154   return Status::ok();
155 }
156 
setShouldSwitchSlotOnReboot(const android::String16 & metadata_filename)157 Status BinderUpdateEngineAndroidService::setShouldSwitchSlotOnReboot(
158     const android::String16& metadata_filename) {
159   Error error;
160   if (!service_delegate_->setShouldSwitchSlotOnReboot(
161           android::String8(metadata_filename).c_str(), &error)) {
162     return ErrorPtrToStatus(error);
163   }
164   return Status::ok();
165 }
166 
resetShouldSwitchSlotOnReboot()167 Status BinderUpdateEngineAndroidService::resetShouldSwitchSlotOnReboot() {
168   Error error;
169   if (!service_delegate_->resetShouldSwitchSlotOnReboot(&error)) {
170     return ErrorPtrToStatus(error);
171   }
172   return Status::ok();
173 }
174 
verifyPayloadApplicable(const android::String16 & metadata_filename,bool * return_value)175 Status BinderUpdateEngineAndroidService::verifyPayloadApplicable(
176     const android::String16& metadata_filename, bool* return_value) {
177   const std::string payload_metadata{
178       android::String8{metadata_filename}.c_str()};
179   LOG(INFO) << "Received a request of verifying payload metadata in "
180             << payload_metadata << ".";
181   Error error;
182   *return_value =
183       service_delegate_->VerifyPayloadApplicable(payload_metadata, &error);
184   if (error.error_code != ErrorCode::kSuccess)
185     return ErrorPtrToStatus(error);
186   return Status::ok();
187 }
188 
UnbindCallback(const IBinder * callback)189 bool BinderUpdateEngineAndroidService::UnbindCallback(const IBinder* callback) {
190   auto it = std::find_if(
191       callbacks_.begin(),
192       callbacks_.end(),
193       [&callback](const android::sp<IUpdateEngineCallback>& elem) {
194         return IUpdateEngineCallback::asBinder(elem).get() == callback;
195       });
196   if (it == callbacks_.end()) {
197     LOG(ERROR) << "Unable to unbind unknown callback.";
198     return false;
199   }
200   callbacks_.erase(it);
201   return true;
202 }
203 
allocateSpaceForPayload(const android::String16 & metadata_filename,const vector<android::String16> & header_kv_pairs,int64_t * return_value)204 Status BinderUpdateEngineAndroidService::allocateSpaceForPayload(
205     const android::String16& metadata_filename,
206     const vector<android::String16>& header_kv_pairs,
207     int64_t* return_value) {
208   const std::string payload_metadata{
209       android::String8{metadata_filename}.c_str()};
210   vector<string> str_headers = ToVecString(header_kv_pairs);
211   LOG(INFO) << "Received a request of allocating space for " << payload_metadata
212             << ".";
213   Error error;
214   *return_value =
215       static_cast<int64_t>(service_delegate_->AllocateSpaceForPayload(
216           payload_metadata, str_headers, &error));
217   if (error.error_code != ErrorCode::kSuccess)
218     return ErrorPtrToStatus(error);
219   return Status::ok();
220 }
221 
222 class CleanupSuccessfulUpdateCallback
223     : public CleanupSuccessfulUpdateCallbackInterface {
224  public:
CleanupSuccessfulUpdateCallback(const android::sp<IUpdateEngineCallback> & callback)225   CleanupSuccessfulUpdateCallback(
226       const android::sp<IUpdateEngineCallback>& callback)
227       : callback_(callback) {}
OnCleanupComplete(int32_t error_code)228   void OnCleanupComplete(int32_t error_code) {
229     ignore_result(callback_->onPayloadApplicationComplete(error_code));
230   }
OnCleanupProgressUpdate(double progress)231   void OnCleanupProgressUpdate(double progress) {
232     ignore_result(callback_->onStatusUpdate(
233         static_cast<int32_t>(
234             update_engine::UpdateStatus::CLEANUP_PREVIOUS_UPDATE),
235         progress));
236   }
RegisterForDeathNotifications(const std::function<void ()> & unbind)237   void RegisterForDeathNotifications(const std::function<void()>& unbind) {
238     const android::sp<android::IBinder>& callback_binder =
239         IUpdateEngineCallback::asBinder(callback_);
240     auto binder_wrapper = android::BinderWrapper::Get();
241     binder_wrapper->RegisterForDeathNotifications(callback_binder, unbind);
242   }
243 
244  private:
245   android::sp<IUpdateEngineCallback> callback_;
246 };
247 
cleanupSuccessfulUpdate(const android::sp<IUpdateEngineCallback> & callback)248 Status BinderUpdateEngineAndroidService::cleanupSuccessfulUpdate(
249     const android::sp<IUpdateEngineCallback>& callback) {
250   Error error;
251   service_delegate_->CleanupSuccessfulUpdate(
252       std::make_unique<CleanupSuccessfulUpdateCallback>(callback), &error);
253   if (error.error_code != ErrorCode::kSuccess)
254     return ErrorPtrToStatus(error);
255   return Status::ok();
256 }
257 
triggerPostinstall(const::android::String16 & partition)258 Status BinderUpdateEngineAndroidService::triggerPostinstall(
259     const ::android::String16& partition) {
260   Error error;
261   service_delegate_->TriggerPostinstall(android::String8(partition).c_str(),
262                                         &error);
263   if (error.error_code != ErrorCode::kSuccess)
264     return ErrorPtrToStatus(error);
265   return Status::ok();
266 }
267 
268 }  // namespace chromeos_update_engine
269