| // |
| // Copyright (C) 2016 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 "trunks/trunks_binder_service.h" |
| |
| #include <sysexits.h> |
| |
| #include <base/bind.h> |
| #include <binderwrapper/binder_wrapper.h> |
| |
| #include "trunks/binder_interface.h" |
| #include "trunks/command_transceiver.h" |
| #include "trunks/error_codes.h" |
| #include "trunks/interface.pb.h" |
| |
| namespace { |
| |
| // If |command| is a valid command protobuf, provides the |command_data| and |
| // returns true. Otherwise, returns false. |
| bool ParseCommandProto(const std::vector<uint8_t>& command, |
| std::string* command_data) { |
| trunks::SendCommandRequest request_proto; |
| if (!request_proto.ParseFromArray(command.data(), command.size()) || |
| !request_proto.has_command() || request_proto.command().empty()) { |
| return false; |
| } |
| *command_data = request_proto.command(); |
| return true; |
| } |
| |
| void CreateResponseProto(const std::string& data, |
| std::vector<uint8_t>* response) { |
| trunks::SendCommandResponse response_proto; |
| response_proto.set_response(data); |
| response->resize(response_proto.ByteSize()); |
| CHECK(response_proto.SerializeToArray(response->data(), response->size())) |
| << "TrunksBinderService: Failed to serialize protobuf."; |
| } |
| |
| } // namespace |
| |
| namespace trunks { |
| |
| int TrunksBinderService::OnInit() { |
| android::BinderWrapper::Create(); |
| if (!watcher_.Init()) { |
| LOG(ERROR) << "TrunksBinderService: BinderWatcher::Init failed."; |
| return EX_UNAVAILABLE; |
| } |
| binder_ = new BinderServiceInternal(this); |
| if (!android::BinderWrapper::Get()->RegisterService( |
| kTrunksServiceName, android::IInterface::asBinder(binder_))) { |
| LOG(ERROR) << "TrunksBinderService: RegisterService failed."; |
| return EX_UNAVAILABLE; |
| } |
| LOG(INFO) << "Trunks: Binder service registered."; |
| return brillo::Daemon::OnInit(); |
| } |
| |
| TrunksBinderService::BinderServiceInternal::BinderServiceInternal( |
| TrunksBinderService* service) |
| : service_(service) {} |
| |
| android::binder::Status TrunksBinderService::BinderServiceInternal::SendCommand( |
| const std::vector<uint8_t>& command, |
| const android::sp<android::trunks::ITrunksClient>& client) { |
| auto callback = |
| base::Bind(&TrunksBinderService::BinderServiceInternal::OnResponse, |
| GetWeakPtr(), client); |
| std::string command_data; |
| if (!ParseCommandProto(command, &command_data)) { |
| LOG(ERROR) << "TrunksBinderService: Bad command data."; |
| callback.Run(CreateErrorResponse(SAPI_RC_BAD_PARAMETER)); |
| return android::binder::Status::ok(); |
| } |
| service_->transceiver_->SendCommand(command_data, callback); |
| return android::binder::Status::ok(); |
| } |
| |
| void TrunksBinderService::BinderServiceInternal::OnResponse( |
| const android::sp<android::trunks::ITrunksClient>& client, |
| const std::string& response) { |
| std::vector<uint8_t> binder_response; |
| CreateResponseProto(response, &binder_response); |
| android::binder::Status status = client->OnCommandResponse(binder_response); |
| if (!status.isOk()) { |
| LOG(ERROR) << "TrunksBinderService: Failed to send response to client: " |
| << status.toString8(); |
| } |
| } |
| |
| android::binder::Status |
| TrunksBinderService::BinderServiceInternal::SendCommandAndWait( |
| const std::vector<uint8_t>& command, |
| std::vector<uint8_t>* response) { |
| std::string command_data; |
| if (!ParseCommandProto(command, &command_data)) { |
| LOG(ERROR) << "TrunksBinderService: Bad command data."; |
| CreateResponseProto(CreateErrorResponse(SAPI_RC_BAD_PARAMETER), response); |
| return android::binder::Status::ok(); |
| } |
| CreateResponseProto(service_->transceiver_->SendCommandAndWait(command_data), |
| response); |
| return android::binder::Status::ok(); |
| } |
| |
| } // namespace trunks |