// Copyright 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 "libweaved/command.h" #include "android/weave/IWeaveCommand.h" #include "common/binder_utils.h" using weaved::binder_utils::ParseDictionary; using weaved::binder_utils::ToString; using weaved::binder_utils::ToString16; using weaved::binder_utils::StatusToError; namespace weaved { namespace { // Converts binder exception code into a weave error code string. std::string BinderExceptionString(int32_t exception_code) { if (exception_code == android::binder::Status::EX_NONE) return "_none"; else if (exception_code == android::binder::Status::EX_SECURITY) return "_security"; else if (exception_code == android::binder::Status::EX_BAD_PARCELABLE) return "_bad_parcelable"; else if (exception_code == android::binder::Status::EX_ILLEGAL_ARGUMENT) return "_illegal_argument"; else if (exception_code == android::binder::Status::EX_NULL_POINTER) return "_null_pointer"; else if (exception_code == android::binder::Status::EX_ILLEGAL_STATE) return "_illegal_state"; else if (exception_code == android::binder::Status::EX_NETWORK_MAIN_THREAD) return "_network_error"; else if (exception_code == android::binder::Status::EX_UNSUPPORTED_OPERATION) return "_unsupported_operation"; else if (exception_code == android::binder::Status::EX_SERVICE_SPECIFIC) return "_general_failure"; return "_unknown"; } } // anonymous namespace Command::Command(const android::sp<android::weave::IWeaveCommand>& proxy) : binder_proxy_{proxy} {} Command::~Command() {} std::string Command::GetID() const { std::string id; android::String16 id16; if (binder_proxy_->getId(&id16).isOk()) id.assign(ToString(id16)); return id; } std::string Command::GetName() const { std::string name; android::String16 name16; if (binder_proxy_->getId(&name16).isOk()) name.assign(ToString(name16)); return name; } std::string Command::GetComponent() const { std::string component; android::String16 component16; if (binder_proxy_->getId(&component16).isOk()) component.assign(ToString(component16)); return component; } Command::State Command::GetState() const { std::string state; android::String16 state16; if (binder_proxy_->getState(&state16).isOk()) state.assign(ToString(state16)); if (state == "queued") return Command::State::kQueued; else if (state == "inProgress") return Command::State::kInProgress; else if (state == "paused") return Command::State::kPaused; else if (state == "error") return Command::State::kError; else if (state == "done") return Command::State::kDone; else if (state == "cancelled") return Command::State::kCancelled; else if (state == "aborted") return Command::State::kAborted; else if (state == "expired") return Command::State::kExpired; LOG(WARNING) << "Unknown command state: " << state; return Command::State::kQueued; } Command::Origin Command::GetOrigin() const { std::string origin; android::String16 origin16; if (binder_proxy_->getState(&origin16).isOk()) origin.assign(ToString(origin16)); if (origin == "local") return Command::Origin::kLocal; else if (origin == "cloud") return Command::Origin::kCloud; LOG(WARNING) << "Unknown command origin: " << origin; return Command::Origin::kLocal; } const base::DictionaryValue& Command::GetParameters() const { if (!parameter_cache_) { android::String16 params_string16; if (!binder_proxy_->getParameters(¶ms_string16).isOk() || !ParseDictionary(params_string16, ¶meter_cache_).isOk()) { parameter_cache_.reset(new base::DictionaryValue); } } return *parameter_cache_; } bool Command::SetProgress(const base::DictionaryValue& progress, brillo::ErrorPtr* error) { return StatusToError(binder_proxy_->setProgress(ToString16(progress)), error); } bool Command::Complete(const base::DictionaryValue& results, brillo::ErrorPtr* error) { return StatusToError(binder_proxy_->complete(ToString16(results)), error); } bool Command::Abort(const std::string& error_code, const std::string& error_message, brillo::ErrorPtr* error) { return StatusToError(binder_proxy_->abort(ToString16(error_code), ToString16(error_message)), error); } bool Command::AbortWithCustomError(const brillo::Error* command_error, brillo::ErrorPtr* error) { std::string error_code = "_" + command_error->GetCode(); return Abort(error_code, command_error->GetMessage(), error); } bool Command::AbortWithCustomError(android::binder::Status status, brillo::ErrorPtr* error) { std::string error_code = BinderExceptionString(status.exceptionCode()); return Abort(error_code, status.exceptionMessage().string(), error); } bool Command::Cancel(brillo::ErrorPtr* error) { return StatusToError(binder_proxy_->cancel(), error); } bool Command::Pause(brillo::ErrorPtr* error) { return StatusToError(binder_proxy_->pause(), error); } bool Command::SetError(const std::string& error_code, const std::string& error_message, brillo::ErrorPtr* error) { return StatusToError(binder_proxy_->setError(ToString16(error_code), ToString16(error_message)), error); } bool Command::SetCustomError(const brillo::Error* command_error, brillo::ErrorPtr* error) { std::string error_code = "_" + command_error->GetCode(); return SetError(error_code, command_error->GetMessage(), error); } bool Command::SetCustomError(android::binder::Status status, brillo::ErrorPtr* error) { std::string error_code = BinderExceptionString(status.exceptionCode()); return SetError(error_code, status.exceptionMessage().string(), error); } } // namespace weave