C++程序  |  96行  |  3.5 KB

//
// 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.
//

namespace tpm_manager {

// Handles protobuf conversions for a binder proxy. Implements ITpmManagerClient
// and acts as a response observer for async requests it sends out. The
// |RequestProtobufType| and |ResponseProtobufType| types can be any protobufs.
template<typename RequestProtobufType, typename ResponseProtobufType>
class BinderProxyHelper {
 public:
  using CallbackType = base::Callback<void(const ResponseProtobufType&)>;
  using GetErrorResponseCallbackType =
      base::Callback<void(ResponseProtobufType*)>;
  using BinderMethodType = base::Callback<android::binder::Status(
      const std::vector<uint8_t>& command_proto,
      const android::sp<android::tpm_manager::ITpmManagerClient>& client)>;

  BinderProxyHelper(const BinderMethodType& method,
                    const CallbackType& callback,
                    const GetErrorResponseCallbackType& get_error_response)
      : method_(method),
        callback_(callback),
        get_error_response_(get_error_response) {}

  void SendErrorResponse() {
    ResponseProtobufType response_proto;
    get_error_response_.Run(&response_proto);
    callback_.Run(response_proto);
  }

  void SendRequest(const RequestProtobufType& request) {
    VLOG(2) << __func__;
    android::sp<ResponseObserver> observer(
        new ResponseObserver(callback_, get_error_response_));
    std::vector<uint8_t> request_bytes;
    request_bytes.resize(request.ByteSize());
    if (!request.SerializeToArray(request_bytes.data(), request_bytes.size())) {
      LOG(ERROR) << "BinderProxyHelper: Failed to serialize protobuf.";
      SendErrorResponse();
      return;
    }
    android::binder::Status status = method_.Run(request_bytes, observer);
    if (!status.isOk()) {
      LOG(ERROR) << "BinderProxyHelper: Binder error: " << status.toString8();
      SendErrorResponse();
      return;
    }
  }

 private:
  class ResponseObserver : public android::tpm_manager::BnTpmManagerClient {
   public:
    ResponseObserver(const CallbackType& callback,
                     const GetErrorResponseCallbackType& get_error_response)
        : callback_(callback), get_error_response_(get_error_response) {}

    // ITpmManagerClient interface.
    android::binder::Status OnCommandResponse(
        const std::vector<uint8_t>& response_proto_data) override {
      VLOG(2) << __func__;
      ResponseProtobufType response_proto;
      if (!response_proto.ParseFromArray(response_proto_data.data(),
                                         response_proto_data.size())) {
        LOG(ERROR) << "BinderProxyHelper: Bad response data.";
        get_error_response_.Run(&response_proto);
      }
      callback_.Run(response_proto);
      return android::binder::Status::ok();
    }

   private:
    CallbackType callback_;
    GetErrorResponseCallbackType get_error_response_;
  };

  BinderMethodType method_;
  CallbackType callback_;
  GetErrorResponseCallbackType get_error_response_;
};

}  // tpm_manager