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_proxy.h"
18
19 #include <base/bind.h>
20 #include <base/callback.h>
21 #include <base/logging.h>
22 #include <binderwrapper/binder_wrapper.h>
23 #include <utils/Errors.h>
24
25 #include "android/trunks/BnTrunksClient.h"
26 #include "android/trunks/BpTrunks.h"
27 #include "trunks/binder_interface.h"
28 #include "trunks/error_codes.h"
29 #include "trunks/interface.pb.h"
30
31 namespace {
32
33 // Implements ITrunksClient and forwards response data to a ResponseCallback.
34 class ResponseObserver : public android::trunks::BnTrunksClient {
35 public:
ResponseObserver(const trunks::CommandTransceiver::ResponseCallback & callback)36 ResponseObserver(const trunks::CommandTransceiver::ResponseCallback& callback)
37 : callback_(callback) {}
38
39 // ITrunksClient interface.
OnCommandResponse(const std::vector<uint8_t> & response_proto_data)40 android::binder::Status OnCommandResponse(
41 const std::vector<uint8_t>& response_proto_data) override {
42 trunks::SendCommandResponse response_proto;
43 if (!response_proto.ParseFromArray(response_proto_data.data(),
44 response_proto_data.size())) {
45 LOG(ERROR) << "TrunksBinderProxy: Bad response data.";
46 callback_.Run(
47 trunks::CreateErrorResponse(trunks::SAPI_RC_MALFORMED_RESPONSE));
48 }
49 callback_.Run(response_proto.response());
50 return android::binder::Status::ok();
51 }
52
53 private:
54 trunks::CommandTransceiver::ResponseCallback callback_;
55 };
56
57 } // namespace
58
59 namespace trunks {
60
Init()61 bool TrunksBinderProxy::Init() {
62 android::sp<android::IBinder> service_binder =
63 android::BinderWrapper::GetOrCreateInstance()->GetService(
64 kTrunksServiceName);
65 if (!service_binder.get()) {
66 LOG(ERROR) << "TrunksBinderProxy: Trunks service does not exist.";
67 return false;
68 }
69 trunks_service_ = new android::trunks::BpTrunks(service_binder);
70 return true;
71 }
72
SendCommand(const std::string & command,const ResponseCallback & callback)73 void TrunksBinderProxy::SendCommand(const std::string& command,
74 const ResponseCallback& callback) {
75 SendCommandRequest command_proto;
76 command_proto.set_command(command);
77 std::vector<uint8_t> command_proto_data;
78 command_proto_data.resize(command_proto.ByteSize());
79 if (!command_proto.SerializeToArray(command_proto_data.data(),
80 command_proto_data.size())) {
81 LOG(ERROR) << "TrunksBinderProxy: Failed to serialize protobuf.";
82 callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
83 return;
84 }
85 android::sp<ResponseObserver> observer(new ResponseObserver(callback));
86 android::binder::Status status =
87 trunks_service_->SendCommand(command_proto_data, observer);
88 if (!status.isOk()) {
89 LOG(ERROR) << "TrunksBinderProxy: Binder error: " << status.toString8();
90 callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
91 return;
92 }
93 }
94
SendCommandAndWait(const std::string & command)95 std::string TrunksBinderProxy::SendCommandAndWait(const std::string& command) {
96 SendCommandRequest command_proto;
97 command_proto.set_command(command);
98 std::vector<uint8_t> command_proto_data;
99 command_proto_data.resize(command_proto.ByteSize());
100 if (!command_proto.SerializeToArray(command_proto_data.data(),
101 command_proto_data.size())) {
102 LOG(ERROR) << "TrunksBinderProxy: Failed to serialize protobuf.";
103 return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
104 }
105 std::vector<uint8_t> response_proto_data;
106 android::binder::Status status = trunks_service_->SendCommandAndWait(
107 command_proto_data, &response_proto_data);
108 if (!status.isOk()) {
109 LOG(ERROR) << "TrunksBinderProxy: Binder error: " << status.toString8();
110 return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
111 }
112 trunks::SendCommandResponse response_proto;
113 if (!response_proto.ParseFromArray(response_proto_data.data(),
114 response_proto_data.size())) {
115 LOG(ERROR) << "TrunksBinderProxy: Bad response data.";
116 return trunks::CreateErrorResponse(trunks::SAPI_RC_MALFORMED_RESPONSE);
117 }
118 return response_proto.response();
119 }
120
121 } // namespace trunks
122