1 /*
2  * Copyright (C) 2018 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 copied from
18 // hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
19 // Please make sure these two file are consistent.
20 
21 #pragma once
22 
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,
62                                                         Arg2T arg2) {
63         this->saved_values = {arg1, arg2};
64     };
65 
66     StorageT saved_values;
67 };
68 
69 // Provides a std::function that takes three or more arguments, and a
70 // buffer wherein the function will store its arguments. The buffer is a
71 // std::tuple whose elements have the same types as the arguments (but
72 // with const and reference modifiers removed).
73 template <typename... ArgT>
74 struct functionArgSaver<std::function<void(ArgT...)>> final {
75     using StorageT = std::tuple<typename std::remove_const<
76         typename std::remove_reference<ArgT>::type>::type...>;
77 
78     std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
79         this->saved_values = {arg...};
80     };
81 
82     StorageT saved_values;
83 };
84 
85 // Invokes |method| on |object|, providing |method| a CallbackT as the
86 // final argument. Returns a copy of the parameters that |method| provided
87 // to CallbackT. (The parameters are returned by value.)
88 template <typename CallbackT, typename MethodT, typename ObjectT,
89           typename... ArgT>
90 typename functionArgSaver<CallbackT>::StorageT invokeMethod(
91     MethodT method, ObjectT object, ArgT&&... methodArg) {
92     functionArgSaver<CallbackT> result_buffer;
93     const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
94                                           result_buffer.saveArgs);
95     EXPECT_TRUE(res.isOk());
96     return result_buffer.saved_values;
97 }
98 
99 // Invokes |void method| on |object| without arguments.
100 template <typename MethodT, typename ObjectT>
101 void invokeVoidMethodWithoutArguments(MethodT method, ObjectT object) {
102     const auto& res = ((*object).*method)();
103     EXPECT_TRUE(res.isOk());
104 }
105 
106 }  // namespace detail
107 }  // namespace
108 
109 // Invokes |method| on |strong_pointer|, passing provided arguments through to
110 // |method|.
111 //
112 // Returns either:
113 // - A copy of the result callback parameter (for callbacks with a single
114 //   parameter), OR
115 // - A pair containing a copy of the result callback parameters (for callbacks
116 //   with two parameters), OR
117 // - A tuple containing a copy of the result callback paramters (for callbacks
118 //   with three or more parameters).
119 //
120 // Example usage:
121 //   EXPECT_EQ(HostapdStatusCode::SUCCESS,
122 //       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatus).code);
123 //   EXPECT_EQ(HostapdStatusCode::SUCCESS,
124 //       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndOneMore)
125 //         .first.code);
126 //   EXPECT_EQ(HostapdStatusCode::SUCCESS, std::get<0>(
127 //       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndTwoMore))
128 //         .code);
129 #define HIDL_INVOKE(strong_pointer, method, ...)                              \
130     (detail::invokeMethod<                                                    \
131         std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
132         &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
133         strong_pointer, ##__VA_ARGS__))
134 
135 // Invokes |void method| on |strong_pointer| without arguments.
136 #define HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(strong_pointer, method)       \
137     (detail::invokeVoidMethodWithoutArguments(                           \
138         &std::remove_reference<decltype(*strong_pointer)>::type::method, \
139         strong_pointer))
140