• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 // This file is modified from
18 // hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
19 
20 #pragma once
21 
22 #include <android-base/logging.h>
23 #include <functional>
24 #include <tuple>
25 #include <type_traits>
26 #include <utility>
27 
28 namespace {
29 namespace detail {
30 template <typename>
31 struct functionArgSaver;
32 
33 // Provides a std::function that takes one argument, and a buffer
34 // wherein the function will store its argument. The buffer has
35 // the same type as the argument, but with const and reference
36 // modifiers removed.
37 template <typename ArgT>
38 struct functionArgSaver<std::function<void(ArgT)>> final {
39   using StorageT = typename std::remove_const<
40       typename std::remove_reference<ArgT>::type>::type;
41 
42   std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
43     this->saved_values = arg;
44   };
45 
46   StorageT saved_values;
47 };
48 
49 // Provides a std::function that takes two arguments, and a buffer
50 // wherein the function will store its arguments. The buffer is a
51 // std::pair, whose elements have the same types as the arguments
52 // (but with const and reference modifiers removed).
53 template <typename Arg1T, typename Arg2T>
54 struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
55   using StorageT =
56       std::pair<typename std::remove_const<
57                     typename std::remove_reference<Arg1T>::type>::type,
58                 typename std::remove_const<
59                     typename std::remove_reference<Arg2T>::type>::type>;
60 
61   std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1, Arg2T arg2) {
62     this->saved_values = {arg1, arg2};
63   };
64 
65   StorageT saved_values;
66 };
67 
68 // Provides a std::function that takes three or more arguments, and a
69 // buffer wherein the function will store its arguments. The buffer is a
70 // std::tuple whose elements have the same types as the arguments (but
71 // with const and reference modifiers removed).
72 template <typename... ArgT>
73 struct functionArgSaver<std::function<void(ArgT...)>> final {
74   using StorageT = std::tuple<typename std::remove_const<
75       typename std::remove_reference<ArgT>::type>::type...>;
76 
77   std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
78     this->saved_values = {arg...};
79   };
80 
81   StorageT saved_values;
82 };
83 
84 // Invokes |method| on |object|, providing |method| a CallbackT as the
85 // final argument. Returns a copy of the parameters that |method| provided
86 // to CallbackT. (The parameters are returned by value.)
87 template <typename CallbackT, typename MethodT, typename ObjectT,
88           typename... ArgT>
89 std::pair<typename functionArgSaver<CallbackT>::StorageT, bool> invokeMethod(
90     MethodT method, ObjectT object, ArgT&&... methodArg) {
91   functionArgSaver<CallbackT> result_buffer;
92   const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
93                                         result_buffer.saveArgs);
94   bool transportStatus = true;
95   if (!res.isOk()) {
96     LOG(ERROR) << " Transport failed " << res.description();
97     transportStatus = false;
98   }
99   return std::make_pair(result_buffer.saved_values, transportStatus);
100 }
101 }  // namespace detail
102 }  // namespace
103 
104 // Invokes |method| on |strong_pointer|, passing provided arguments through to
105 // |method|.
106 //
107 // Returns either:
108 // - A copy of the result callback parameter (for callbacks with a single
109 //   parameter), OR
110 // - A pair containing a copy of the result callback parameters (for callbacks
111 //   with two parameters), OR
112 // - A tuple containing a copy of the result callback paramters (for callbacks
113 //   with three or more parameters).
114 //
115 // Example usage:
116 //   EXPECT_EQ(WifiStatusCode::SUCCESS,
117 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code);
118 //   EXPECT_EQ(WifiStatusCode::SUCCESS,
119 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore)
120 //         .first.code);
121 //   EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>(
122 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore))
123 //         .code);
124 #define HIDL_INVOKE(strong_pointer, method, ...)                            \
125   (detail::invokeMethod<                                                    \
126       std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
127       &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
128       strong_pointer, ##__VA_ARGS__))
129