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 namespace tpm_manager {
18 
19 // Handles protobuf conversions for a binder proxy. Implements ITpmManagerClient
20 // and acts as a response observer for async requests it sends out. The
21 // |RequestProtobufType| and |ResponseProtobufType| types can be any protobufs.
22 template<typename RequestProtobufType, typename ResponseProtobufType>
23 class BinderProxyHelper {
24  public:
25   using CallbackType = base::Callback<void(const ResponseProtobufType&)>;
26   using GetErrorResponseCallbackType =
27       base::Callback<void(ResponseProtobufType*)>;
28   using BinderMethodType = base::Callback<android::binder::Status(
29       const std::vector<uint8_t>& command_proto,
30       const android::sp<android::tpm_manager::ITpmManagerClient>& client)>;
31 
BinderProxyHelper(const BinderMethodType & method,const CallbackType & callback,const GetErrorResponseCallbackType & get_error_response)32   BinderProxyHelper(const BinderMethodType& method,
33                     const CallbackType& callback,
34                     const GetErrorResponseCallbackType& get_error_response)
35       : method_(method),
36         callback_(callback),
37         get_error_response_(get_error_response) {}
38 
SendErrorResponse()39   void SendErrorResponse() {
40     ResponseProtobufType response_proto;
41     get_error_response_.Run(&response_proto);
42     callback_.Run(response_proto);
43   }
44 
SendRequest(const RequestProtobufType & request)45   void SendRequest(const RequestProtobufType& request) {
46     VLOG(2) << __func__;
47     android::sp<ResponseObserver> observer(
48         new ResponseObserver(callback_, get_error_response_));
49     std::vector<uint8_t> request_bytes;
50     request_bytes.resize(request.ByteSize());
51     if (!request.SerializeToArray(request_bytes.data(), request_bytes.size())) {
52       LOG(ERROR) << "BinderProxyHelper: Failed to serialize protobuf.";
53       SendErrorResponse();
54       return;
55     }
56     android::binder::Status status = method_.Run(request_bytes, observer);
57     if (!status.isOk()) {
58       LOG(ERROR) << "BinderProxyHelper: Binder error: " << status.toString8();
59       SendErrorResponse();
60       return;
61     }
62   }
63 
64  private:
65   class ResponseObserver : public android::tpm_manager::BnTpmManagerClient {
66    public:
ResponseObserver(const CallbackType & callback,const GetErrorResponseCallbackType & get_error_response)67     ResponseObserver(const CallbackType& callback,
68                      const GetErrorResponseCallbackType& get_error_response)
69         : callback_(callback), get_error_response_(get_error_response) {}
70 
71     // ITpmManagerClient interface.
OnCommandResponse(const std::vector<uint8_t> & response_proto_data)72     android::binder::Status OnCommandResponse(
73         const std::vector<uint8_t>& response_proto_data) override {
74       VLOG(2) << __func__;
75       ResponseProtobufType response_proto;
76       if (!response_proto.ParseFromArray(response_proto_data.data(),
77                                          response_proto_data.size())) {
78         LOG(ERROR) << "BinderProxyHelper: Bad response data.";
79         get_error_response_.Run(&response_proto);
80       }
81       callback_.Run(response_proto);
82       return android::binder::Status::ok();
83     }
84 
85    private:
86     CallbackType callback_;
87     GetErrorResponseCallbackType get_error_response_;
88   };
89 
90   BinderMethodType method_;
91   CallbackType callback_;
92   GetErrorResponseCallbackType get_error_response_;
93 };
94 
95 }  // tpm_manager
96