// // 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/client_library/client_binder.h" #include <binder/IServiceManager.h> #include <base/message_loop/message_loop.h> #include <utils/String8.h> #include "update_engine/common_service.h" #include "update_engine/parcelable_update_engine_status.h" #include "update_engine/update_status_utils.h" using android::OK; using android::String16; using android::String8; using android::binder::Status; using android::brillo::ParcelableUpdateEngineStatus; using android::getService; using chromeos_update_engine::StringToUpdateStatus; using chromeos_update_engine::UpdateEngineService; using std::string; namespace update_engine { namespace internal { bool BinderUpdateEngineClient::Init() { if (!binder_watcher_.Init()) return false; return getService(String16{"android.brillo.UpdateEngineService"}, &service_) == OK; } bool BinderUpdateEngineClient::AttemptUpdate(const string& in_app_version, const string& in_omaha_url, bool at_user_request) { return service_->AttemptUpdate(String16{in_app_version.c_str()}, String16{in_omaha_url.c_str()}, at_user_request ? 0 : UpdateEngineService::kAttemptUpdateFlagNonInteractive).isOk(); } bool BinderUpdateEngineClient::GetStatus(int64_t* out_last_checked_time, double* out_progress, UpdateStatus* out_update_status, string* out_new_version, int64_t* out_new_size) const { ParcelableUpdateEngineStatus status; if (!service_->GetStatus(&status).isOk()) return false; *out_last_checked_time = status.last_checked_time_; *out_progress = status.progress_; StringToUpdateStatus(String8{status.current_operation_}.string(), out_update_status); *out_new_version = String8{status.new_version_}.string(); *out_new_size = status.new_size_; return true; } bool BinderUpdateEngineClient::SetCohortHint(const string& in_cohort_hint) { return service_->SetCohortHint(String16{in_cohort_hint.c_str()}).isOk(); } bool BinderUpdateEngineClient::GetCohortHint(string* out_cohort_hint) const { String16 out_as_string16; if (!service_->GetCohortHint(&out_as_string16).isOk()) return false; *out_cohort_hint = String8{out_as_string16}.string(); return true; } bool BinderUpdateEngineClient::SetUpdateOverCellularPermission(bool allowed) { return service_->SetUpdateOverCellularPermission(allowed).isOk(); } bool BinderUpdateEngineClient::GetUpdateOverCellularPermission( bool* allowed) const { return service_->GetUpdateOverCellularPermission(allowed).isOk(); } bool BinderUpdateEngineClient::SetP2PUpdatePermission(bool enabled) { return service_->SetP2PUpdatePermission(enabled).isOk(); } bool BinderUpdateEngineClient::GetP2PUpdatePermission(bool* enabled) const { return service_->GetP2PUpdatePermission(enabled).isOk(); } bool BinderUpdateEngineClient::Rollback(bool powerwash) { return service_->AttemptRollback(powerwash).isOk(); } bool BinderUpdateEngineClient::GetRollbackPartition( string* rollback_partition) const { String16 out_as_string16; if (!service_->GetRollbackPartition(&out_as_string16).isOk()) return false; *rollback_partition = String8{out_as_string16}.string(); return true; } bool BinderUpdateEngineClient::GetPrevVersion(string* prev_version) const { String16 out_as_string16; if (!service_->GetPrevVersion(&out_as_string16).isOk()) return false; *prev_version = String8{out_as_string16}.string(); return true; } void BinderUpdateEngineClient::RebootIfNeeded() { if (!service_->RebootIfNeeded().isOk()) { // Reboot error code doesn't necessarily mean that a reboot // failed. For example, D-Bus may be shutdown before we receive the // result. LOG(INFO) << "RebootIfNeeded() failure ignored."; } } bool BinderUpdateEngineClient::ResetStatus() { return service_->ResetStatus().isOk(); } Status BinderUpdateEngineClient::StatusUpdateCallback::HandleStatusUpdate( int64_t last_checked_time, double progress, const String16& current_operation, const String16& new_version, int64_t new_size) { UpdateStatus update_status; StringToUpdateStatus(String8{current_operation}.string(), &update_status); for (auto& handler : client_->handlers_) { handler->HandleStatusUpdate(last_checked_time, progress, update_status, String8{new_version}.string(), new_size); } return Status::ok(); } bool BinderUpdateEngineClient::RegisterStatusUpdateHandler( StatusUpdateHandler* handler) { if (!status_callback_.get()) { status_callback_ = new BinderUpdateEngineClient::StatusUpdateCallback(this); if (!service_->RegisterStatusCallback(status_callback_).isOk()) { return false; } } handlers_.push_back(handler); int64_t last_checked_time; double progress; UpdateStatus update_status; string new_version; int64_t new_size; if (!GetStatus(&last_checked_time, &progress, &update_status, &new_version, &new_size)) { handler->IPCError("Could not get status from binder service"); } handler->HandleStatusUpdate(last_checked_time, progress, update_status, new_version, new_size); return true; } bool BinderUpdateEngineClient::UnregisterStatusUpdateHandler( StatusUpdateHandler* handler) { auto it = std::find(handlers_.begin(), handlers_.end(), handler); if (it != handlers_.end()) { handlers_.erase(it); return true; } return false; } bool BinderUpdateEngineClient::SetTargetChannel(const string& in_target_channel, bool allow_powerwash) { return service_->SetChannel(String16{in_target_channel.c_str()}, allow_powerwash).isOk(); } bool BinderUpdateEngineClient::GetTargetChannel(string* out_channel) const { String16 out_as_string16; if (!service_->GetChannel(false, &out_as_string16).isOk()) return false; *out_channel = String8{out_as_string16}.string(); return true; } bool BinderUpdateEngineClient::GetChannel(string* out_channel) const { String16 out_as_string16; if (!service_->GetChannel(true, &out_as_string16).isOk()) return false; *out_channel = String8{out_as_string16}.string(); return true; } bool BinderUpdateEngineClient::GetLastAttemptError( int32_t* last_attempt_error) const { int out_as_int; if (!service_->GetLastAttemptError(&out_as_int).isOk()) return false; *last_attempt_error = out_as_int; return true; } bool BinderUpdateEngineClient::GetEolStatus(int32_t* eol_status) const { int out_as_int; if (!service_->GetEolStatus(&out_as_int).isOk()) return false; *eol_status = out_as_int; return true; } } // namespace internal } // namespace update_engine