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 "interface.pb.h" 28 29 namespace { 30 31 // If |command| is a valid command protobuf, provides the |command_data| and 32 // returns true. Otherwise, returns false. 33 bool 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 44 void 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 55 namespace trunks { 56 57 int 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 73 TrunksBinderService::BinderServiceInternal::BinderServiceInternal( 74 TrunksBinderService* service) 75 : service_(service) {} 76 77 android::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 93 void 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 105 android::binder::Status 106 TrunksBinderService::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