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 <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 using android::binder::Status; 28 using android::os::IUpdateEngineCallback; 29 using android::os::ParcelFileDescriptor; 30 using std::string; 31 using std::vector; 32 using update_engine::UpdateEngineStatus; 33 34 namespace { 35 Status ErrorPtrToStatus(const brillo::ErrorPtr& error) { 36 return Status::fromServiceSpecificError( 37 1, android::String8{error->GetMessage().c_str()}); 38 } 39 40 vector<string> ToVecString(const vector<android::String16>& inp) { 41 vector<string> out; 42 out.reserve(inp.size()); 43 for (const auto& e : inp) { 44 out.emplace_back(android::String8{e}.string()); 45 } 46 return out; 47 } 48 49 } // namespace 50 51 namespace chromeos_update_engine { 52 53 BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService( 54 ServiceDelegateAndroidInterface* service_delegate) 55 : service_delegate_(service_delegate) {} 56 57 void BinderUpdateEngineAndroidService::SendStatusUpdate( 58 const UpdateEngineStatus& update_engine_status) { 59 last_status_ = static_cast<int>(update_engine_status.status); 60 last_progress_ = update_engine_status.progress; 61 for (auto& callback : callbacks_) { 62 callback->onStatusUpdate(last_status_, last_progress_); 63 } 64 } 65 66 void BinderUpdateEngineAndroidService::SendPayloadApplicationComplete( 67 ErrorCode error_code) { 68 for (auto& callback : callbacks_) { 69 callback->onPayloadApplicationComplete(static_cast<int>(error_code)); 70 } 71 } 72 73 Status BinderUpdateEngineAndroidService::bind( 74 const android::sp<IUpdateEngineCallback>& callback, bool* return_value) { 75 // Send an status update on connection (except when no update sent so far). 76 // Even though the status update is oneway, it still returns an erroneous 77 // status in case of a selinux denial. We should at least check this status 78 // and fails the binding. 79 if (last_status_ != -1) { 80 auto status = callback->onStatusUpdate(last_status_, last_progress_); 81 if (!status.isOk()) { 82 LOG(ERROR) << "Failed to call onStatusUpdate() from callback: " 83 << status.toString8(); 84 *return_value = false; 85 return Status::ok(); 86 } 87 } 88 89 callbacks_.emplace_back(callback); 90 91 const android::sp<IBinder>& callback_binder = 92 IUpdateEngineCallback::asBinder(callback); 93 auto binder_wrapper = android::BinderWrapper::Get(); 94 binder_wrapper->RegisterForDeathNotifications( 95 callback_binder, 96 base::Bind( 97 base::IgnoreResult(&BinderUpdateEngineAndroidService::UnbindCallback), 98 base::Unretained(this), 99 base::Unretained(callback_binder.get()))); 100 101 *return_value = true; 102 return Status::ok(); 103 } 104 105 Status BinderUpdateEngineAndroidService::unbind( 106 const android::sp<IUpdateEngineCallback>& callback, bool* return_value) { 107 const android::sp<IBinder>& callback_binder = 108 IUpdateEngineCallback::asBinder(callback); 109 auto binder_wrapper = android::BinderWrapper::Get(); 110 binder_wrapper->UnregisterForDeathNotifications(callback_binder); 111 112 *return_value = UnbindCallback(callback_binder.get()); 113 return Status::ok(); 114 } 115 116 Status BinderUpdateEngineAndroidService::applyPayload( 117 const android::String16& url, 118 int64_t payload_offset, 119 int64_t payload_size, 120 const vector<android::String16>& header_kv_pairs) { 121 const string payload_url{android::String8{url}.string()}; 122 vector<string> str_headers = ToVecString(header_kv_pairs); 123 124 brillo::ErrorPtr error; 125 if (!service_delegate_->ApplyPayload( 126 payload_url, payload_offset, payload_size, str_headers, &error)) { 127 return ErrorPtrToStatus(error); 128 } 129 return Status::ok(); 130 } 131 132 Status BinderUpdateEngineAndroidService::applyPayloadFd( 133 const ParcelFileDescriptor& pfd, 134 int64_t payload_offset, 135 int64_t payload_size, 136 const vector<android::String16>& header_kv_pairs) { 137 vector<string> str_headers = ToVecString(header_kv_pairs); 138 139 brillo::ErrorPtr error; 140 if (!service_delegate_->ApplyPayload( 141 pfd.get(), payload_offset, payload_size, str_headers, &error)) { 142 return ErrorPtrToStatus(error); 143 } 144 return Status::ok(); 145 } 146 147 Status BinderUpdateEngineAndroidService::suspend() { 148 brillo::ErrorPtr error; 149 if (!service_delegate_->SuspendUpdate(&error)) 150 return ErrorPtrToStatus(error); 151 return Status::ok(); 152 } 153 154 Status BinderUpdateEngineAndroidService::resume() { 155 brillo::ErrorPtr error; 156 if (!service_delegate_->ResumeUpdate(&error)) 157 return ErrorPtrToStatus(error); 158 return Status::ok(); 159 } 160 161 Status BinderUpdateEngineAndroidService::cancel() { 162 brillo::ErrorPtr error; 163 if (!service_delegate_->CancelUpdate(&error)) 164 return ErrorPtrToStatus(error); 165 return Status::ok(); 166 } 167 168 Status BinderUpdateEngineAndroidService::resetStatus() { 169 brillo::ErrorPtr error; 170 if (!service_delegate_->ResetStatus(&error)) 171 return ErrorPtrToStatus(error); 172 return Status::ok(); 173 } 174 175 Status BinderUpdateEngineAndroidService::verifyPayloadApplicable( 176 const android::String16& metadata_filename, bool* return_value) { 177 const std::string payload_metadata{ 178 android::String8{metadata_filename}.string()}; 179 LOG(INFO) << "Received a request of verifying payload metadata in " 180 << payload_metadata << "."; 181 brillo::ErrorPtr error; 182 *return_value = 183 service_delegate_->VerifyPayloadApplicable(payload_metadata, &error); 184 if (error != nullptr) 185 return ErrorPtrToStatus(error); 186 return Status::ok(); 187 } 188 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 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}.string()}; 210 vector<string> str_headers = ToVecString(header_kv_pairs); 211 LOG(INFO) << "Received a request of allocating space for " << payload_metadata 212 << "."; 213 brillo::ErrorPtr error; 214 *return_value = 215 static_cast<int64_t>(service_delegate_->AllocateSpaceForPayload( 216 payload_metadata, str_headers, &error)); 217 if (error != nullptr) 218 return ErrorPtrToStatus(error); 219 return Status::ok(); 220 } 221 222 class CleanupSuccessfulUpdateCallback 223 : public CleanupSuccessfulUpdateCallbackInterface { 224 public: 225 CleanupSuccessfulUpdateCallback( 226 const android::sp<IUpdateEngineCallback>& callback) 227 : callback_(callback) {} 228 void OnCleanupComplete(int32_t error_code) { 229 ignore_result(callback_->onPayloadApplicationComplete(error_code)); 230 } 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 } 237 void RegisterForDeathNotifications(base::Closure 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 248 Status BinderUpdateEngineAndroidService::cleanupSuccessfulUpdate( 249 const android::sp<IUpdateEngineCallback>& callback) { 250 brillo::ErrorPtr error; 251 service_delegate_->CleanupSuccessfulUpdate( 252 std::make_unique<CleanupSuccessfulUpdateCallback>(callback), &error); 253 if (error != nullptr) 254 return ErrorPtrToStatus(error); 255 return Status::ok(); 256 } 257 258 } // namespace chromeos_update_engine 259