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