Home | History | Annotate | Download | only in trunks
      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