1// 2// Copyright (C) 2016 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 "trunks/trunks_binder_service.h" 18 19#include <sysexits.h> 20 21#include <base/bind.h> 22#include <binderwrapper/binder_wrapper.h> 23 24#include "trunks/binder_interface.h" 25#include "trunks/command_transceiver.h" 26#include "trunks/error_codes.h" 27#include "trunks/interface.pb.h" 28 29namespace { 30 31// If |command| is a valid command protobuf, provides the |command_data| and 32// returns true. Otherwise, returns false. 33bool ParseCommandProto(const std::vector<uint8_t>& command, 34 std::string* command_data) { 35 trunks::SendCommandRequest request_proto; 36 if (!request_proto.ParseFromArray(command.data(), command.size()) || 37 !request_proto.has_command() || request_proto.command().empty()) { 38 return false; 39 } 40 *command_data = request_proto.command(); 41 return true; 42} 43 44void CreateResponseProto(const std::string& data, 45 std::vector<uint8_t>* response) { 46 trunks::SendCommandResponse response_proto; 47 response_proto.set_response(data); 48 response->resize(response_proto.ByteSize()); 49 CHECK(response_proto.SerializeToArray(response->data(), response->size())) 50 << "TrunksBinderService: Failed to serialize protobuf."; 51} 52 53} // namespace 54 55namespace trunks { 56 57int TrunksBinderService::OnInit() { 58 android::BinderWrapper::Create(); 59 if (!watcher_.Init()) { 60 LOG(ERROR) << "TrunksBinderService: BinderWatcher::Init failed."; 61 return EX_UNAVAILABLE; 62 } 63 binder_ = new BinderServiceInternal(this); 64 if (!android::BinderWrapper::Get()->RegisterService( 65 kTrunksServiceName, android::IInterface::asBinder(binder_))) { 66 LOG(ERROR) << "TrunksBinderService: RegisterService failed."; 67 return EX_UNAVAILABLE; 68 } 69 LOG(INFO) << "Trunks: Binder service registered."; 70 return brillo::Daemon::OnInit(); 71} 72 73TrunksBinderService::BinderServiceInternal::BinderServiceInternal( 74 TrunksBinderService* service) 75 : service_(service) {} 76 77android::binder::Status TrunksBinderService::BinderServiceInternal::SendCommand( 78 const std::vector<uint8_t>& command, 79 const android::sp<android::trunks::ITrunksClient>& client) { 80 auto callback = 81 base::Bind(&TrunksBinderService::BinderServiceInternal::OnResponse, 82 GetWeakPtr(), client); 83 std::string command_data; 84 if (!ParseCommandProto(command, &command_data)) { 85 LOG(ERROR) << "TrunksBinderService: Bad command data."; 86 callback.Run(CreateErrorResponse(SAPI_RC_BAD_PARAMETER)); 87 return android::binder::Status::ok(); 88 } 89 service_->transceiver_->SendCommand(command_data, callback); 90 return android::binder::Status::ok(); 91} 92 93void TrunksBinderService::BinderServiceInternal::OnResponse( 94 const android::sp<android::trunks::ITrunksClient>& client, 95 const std::string& response) { 96 std::vector<uint8_t> binder_response; 97 CreateResponseProto(response, &binder_response); 98 android::binder::Status status = client->OnCommandResponse(binder_response); 99 if (!status.isOk()) { 100 LOG(ERROR) << "TrunksBinderService: Failed to send response to client: " 101 << status.toString8(); 102 } 103} 104 105android::binder::Status 106TrunksBinderService::BinderServiceInternal::SendCommandAndWait( 107 const std::vector<uint8_t>& command, 108 std::vector<uint8_t>* response) { 109 std::string command_data; 110 if (!ParseCommandProto(command, &command_data)) { 111 LOG(ERROR) << "TrunksBinderService: Bad command data."; 112 CreateResponseProto(CreateErrorResponse(SAPI_RC_BAD_PARAMETER), response); 113 return android::binder::Status::ok(); 114 } 115 CreateResponseProto(service_->transceiver_->SendCommandAndWait(command_data), 116 response); 117 return android::binder::Status::ok(); 118} 119 120} // namespace trunks 121