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 
29 namespace {
30 
31 // If |command| is a valid command protobuf, provides the |command_data| and
32 // returns true. Otherwise, returns false.
ParseCommandProto(const std::vector<uint8_t> & command,std::string * command_data)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 
CreateResponseProto(const std::string & data,std::vector<uint8_t> * response)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 
OnInit()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 
BinderServiceInternal(TrunksBinderService * service)73 TrunksBinderService::BinderServiceInternal::BinderServiceInternal(
74     TrunksBinderService* service)
75     : service_(service) {}
76 
SendCommand(const std::vector<uint8_t> & command,const android::sp<android::trunks::ITrunksClient> & client)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 
OnResponse(const android::sp<android::trunks::ITrunksClient> & client,const std::string & response)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
SendCommandAndWait(const std::vector<uint8_t> & command,std::vector<uint8_t> * response)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