//
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "trunks/trunks_binder_proxy.h"
#include <base/bind.h>
#include <base/callback.h>
#include <base/logging.h>
#include <binderwrapper/binder_wrapper.h>
#include <utils/Errors.h>
#include "android/trunks/BnTrunksClient.h"
#include "android/trunks/BpTrunks.h"
#include "trunks/binder_interface.h"
#include "trunks/error_codes.h"
#include "trunks/interface.pb.h"
namespace {
// Implements ITrunksClient and forwards response data to a ResponseCallback.
class ResponseObserver : public android::trunks::BnTrunksClient {
public:
ResponseObserver(const trunks::CommandTransceiver::ResponseCallback& callback)
: callback_(callback) {}
// ITrunksClient interface.
android::binder::Status OnCommandResponse(
const std::vector<uint8_t>& response_proto_data) override {
trunks::SendCommandResponse response_proto;
if (!response_proto.ParseFromArray(response_proto_data.data(),
response_proto_data.size())) {
LOG(ERROR) << "TrunksBinderProxy: Bad response data.";
callback_.Run(
trunks::CreateErrorResponse(trunks::SAPI_RC_MALFORMED_RESPONSE));
}
callback_.Run(response_proto.response());
return android::binder::Status::ok();
}
private:
trunks::CommandTransceiver::ResponseCallback callback_;
};
} // namespace
namespace trunks {
bool TrunksBinderProxy::Init() {
android::sp<android::IBinder> service_binder =
android::BinderWrapper::GetOrCreateInstance()->GetService(
kTrunksServiceName);
if (!service_binder.get()) {
LOG(ERROR) << "TrunksBinderProxy: Trunks service does not exist.";
return false;
}
trunks_service_ = new android::trunks::BpTrunks(service_binder);
return true;
}
void TrunksBinderProxy::SendCommand(const std::string& command,
const ResponseCallback& callback) {
SendCommandRequest command_proto;
command_proto.set_command(command);
std::vector<uint8_t> command_proto_data;
command_proto_data.resize(command_proto.ByteSize());
if (!command_proto.SerializeToArray(command_proto_data.data(),
command_proto_data.size())) {
LOG(ERROR) << "TrunksBinderProxy: Failed to serialize protobuf.";
callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
return;
}
android::sp<ResponseObserver> observer(new ResponseObserver(callback));
android::binder::Status status =
trunks_service_->SendCommand(command_proto_data, observer);
if (!status.isOk()) {
LOG(ERROR) << "TrunksBinderProxy: Binder error: " << status.toString8();
callback.Run(CreateErrorResponse(TRUNKS_RC_IPC_ERROR));
return;
}
}
std::string TrunksBinderProxy::SendCommandAndWait(const std::string& command) {
SendCommandRequest command_proto;
command_proto.set_command(command);
std::vector<uint8_t> command_proto_data;
command_proto_data.resize(command_proto.ByteSize());
if (!command_proto.SerializeToArray(command_proto_data.data(),
command_proto_data.size())) {
LOG(ERROR) << "TrunksBinderProxy: Failed to serialize protobuf.";
return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
}
std::vector<uint8_t> response_proto_data;
android::binder::Status status = trunks_service_->SendCommandAndWait(
command_proto_data, &response_proto_data);
if (!status.isOk()) {
LOG(ERROR) << "TrunksBinderProxy: Binder error: " << status.toString8();
return CreateErrorResponse(TRUNKS_RC_IPC_ERROR);
}
trunks::SendCommandResponse response_proto;
if (!response_proto.ParseFromArray(response_proto_data.data(),
response_proto_data.size())) {
LOG(ERROR) << "TrunksBinderProxy: Bad response data.";
return trunks::CreateErrorResponse(trunks::SAPI_RC_MALFORMED_RESPONSE);
}
return response_proto.response();
}
} // namespace trunks