summaryrefslogtreecommitdiff
path: root/aosp/binder_service_android.cc
diff options
context:
space:
mode:
Diffstat (limited to 'aosp/binder_service_android.cc')
-rw-r--r--aosp/binder_service_android.cc243
1 files changed, 243 insertions, 0 deletions
diff --git a/aosp/binder_service_android.cc b/aosp/binder_service_android.cc
new file mode 100644
index 00000000..ed76c4a8
--- /dev/null
+++ b/aosp/binder_service_android.cc
@@ -0,0 +1,243 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/aosp/binder_service_android.h"
+
+#include <memory>
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/errors/error.h>
+#include <utils/String8.h>
+
+#include "update_engine/aosp/binder_service_android_common.h"
+
+using android::binder::Status;
+using android::os::IUpdateEngineCallback;
+using android::os::ParcelFileDescriptor;
+using std::string;
+using std::vector;
+using update_engine::UpdateEngineStatus;
+
+namespace chromeos_update_engine {
+
+BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
+ ServiceDelegateAndroidInterface* service_delegate)
+ : service_delegate_(service_delegate) {}
+
+void BinderUpdateEngineAndroidService::SendStatusUpdate(
+ const UpdateEngineStatus& update_engine_status) {
+ last_status_ = static_cast<int>(update_engine_status.status);
+ last_progress_ = update_engine_status.progress;
+ for (auto& callback : callbacks_) {
+ callback->onStatusUpdate(last_status_, last_progress_);
+ }
+}
+
+void BinderUpdateEngineAndroidService::SendPayloadApplicationComplete(
+ ErrorCode error_code) {
+ for (auto& callback : callbacks_) {
+ callback->onPayloadApplicationComplete(static_cast<int>(error_code));
+ }
+}
+
+Status BinderUpdateEngineAndroidService::bind(
+ const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
+ // Send an status update on connection (except when no update sent so far).
+ // Even though the status update is oneway, it still returns an erroneous
+ // status in case of a selinux denial. We should at least check this status
+ // and fails the binding.
+ if (last_status_ != -1) {
+ auto status = callback->onStatusUpdate(last_status_, last_progress_);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Failed to call onStatusUpdate() from callback: "
+ << status.toString8();
+ *return_value = false;
+ return Status::ok();
+ }
+ }
+
+ callbacks_.emplace_back(callback);
+
+ const android::sp<IBinder>& callback_binder =
+ IUpdateEngineCallback::asBinder(callback);
+ auto binder_wrapper = android::BinderWrapper::Get();
+ binder_wrapper->RegisterForDeathNotifications(
+ callback_binder,
+ base::Bind(
+ base::IgnoreResult(&BinderUpdateEngineAndroidService::UnbindCallback),
+ base::Unretained(this),
+ base::Unretained(callback_binder.get())));
+
+ *return_value = true;
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::unbind(
+ const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
+ const android::sp<IBinder>& callback_binder =
+ IUpdateEngineCallback::asBinder(callback);
+ auto binder_wrapper = android::BinderWrapper::Get();
+ binder_wrapper->UnregisterForDeathNotifications(callback_binder);
+
+ *return_value = UnbindCallback(callback_binder.get());
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::applyPayload(
+ const android::String16& url,
+ int64_t payload_offset,
+ int64_t payload_size,
+ const vector<android::String16>& header_kv_pairs) {
+ const string payload_url{android::String8{url}.string()};
+ vector<string> str_headers = ToVecString(header_kv_pairs);
+
+ brillo::ErrorPtr error;
+ if (!service_delegate_->ApplyPayload(
+ payload_url, payload_offset, payload_size, str_headers, &error)) {
+ return ErrorPtrToStatus(error);
+ }
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::applyPayloadFd(
+ const ParcelFileDescriptor& pfd,
+ int64_t payload_offset,
+ int64_t payload_size,
+ const vector<android::String16>& header_kv_pairs) {
+ vector<string> str_headers = ToVecString(header_kv_pairs);
+
+ brillo::ErrorPtr error;
+ if (!service_delegate_->ApplyPayload(
+ pfd.get(), payload_offset, payload_size, str_headers, &error)) {
+ return ErrorPtrToStatus(error);
+ }
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::suspend() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->SuspendUpdate(&error))
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::resume() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->ResumeUpdate(&error))
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::cancel() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->CancelUpdate(&error))
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::resetStatus() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->ResetStatus(&error))
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidService::verifyPayloadApplicable(
+ const android::String16& metadata_filename, bool* return_value) {
+ const std::string payload_metadata{
+ android::String8{metadata_filename}.string()};
+ LOG(INFO) << "Received a request of verifying payload metadata in "
+ << payload_metadata << ".";
+ brillo::ErrorPtr error;
+ *return_value =
+ service_delegate_->VerifyPayloadApplicable(payload_metadata, &error);
+ if (error != nullptr)
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+bool BinderUpdateEngineAndroidService::UnbindCallback(const IBinder* callback) {
+ auto it = std::find_if(
+ callbacks_.begin(),
+ callbacks_.end(),
+ [&callback](const android::sp<IUpdateEngineCallback>& elem) {
+ return IUpdateEngineCallback::asBinder(elem).get() == callback;
+ });
+ if (it == callbacks_.end()) {
+ LOG(ERROR) << "Unable to unbind unknown callback.";
+ return false;
+ }
+ callbacks_.erase(it);
+ return true;
+}
+
+Status BinderUpdateEngineAndroidService::allocateSpaceForPayload(
+ const android::String16& metadata_filename,
+ const vector<android::String16>& header_kv_pairs,
+ int64_t* return_value) {
+ const std::string payload_metadata{
+ android::String8{metadata_filename}.string()};
+ vector<string> str_headers = ToVecString(header_kv_pairs);
+ LOG(INFO) << "Received a request of allocating space for " << payload_metadata
+ << ".";
+ brillo::ErrorPtr error;
+ *return_value =
+ static_cast<int64_t>(service_delegate_->AllocateSpaceForPayload(
+ payload_metadata, str_headers, &error));
+ if (error != nullptr)
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+class CleanupSuccessfulUpdateCallback
+ : public CleanupSuccessfulUpdateCallbackInterface {
+ public:
+ CleanupSuccessfulUpdateCallback(
+ const android::sp<IUpdateEngineCallback>& callback)
+ : callback_(callback) {}
+ void OnCleanupComplete(int32_t error_code) {
+ ignore_result(callback_->onPayloadApplicationComplete(error_code));
+ }
+ void OnCleanupProgressUpdate(double progress) {
+ ignore_result(callback_->onStatusUpdate(
+ static_cast<int32_t>(
+ update_engine::UpdateStatus::CLEANUP_PREVIOUS_UPDATE),
+ progress));
+ }
+ void RegisterForDeathNotifications(base::Closure unbind) {
+ const android::sp<android::IBinder>& callback_binder =
+ IUpdateEngineCallback::asBinder(callback_);
+ auto binder_wrapper = android::BinderWrapper::Get();
+ binder_wrapper->RegisterForDeathNotifications(callback_binder, unbind);
+ }
+
+ private:
+ android::sp<IUpdateEngineCallback> callback_;
+};
+
+Status BinderUpdateEngineAndroidService::cleanupSuccessfulUpdate(
+ const android::sp<IUpdateEngineCallback>& callback) {
+ brillo::ErrorPtr error;
+ service_delegate_->CleanupSuccessfulUpdate(
+ std::make_unique<CleanupSuccessfulUpdateCallback>(callback), &error);
+ if (error != nullptr)
+ return ErrorPtrToStatus(error);
+ return Status::ok();
+}
+
+} // namespace chromeos_update_engine