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 #include <functional>
18 #include <type_traits>
19 
20 #include <hidl/Status.h>
21 #include <utils/RefBase.h>
22 #include <utils/StrongPointer.h>
23 
24 #include "wifi_hidl_call_util.h"
25 
26 namespace {
27 /*
28  * Example of a user-defined data-type.
29  *
30  * Used to verify that, within the internals of HIDL_INVOKE,
31  * reference parameters are stored by copy.
32  */
33 class Dummy {};
34 
35 /*
36  * Example of what a HIDL-generated proxy might look like.
37  */
38 class IExample : public ::android::RefBase {
39    public:
40     // The callback type, for a method called startWithCallbackCopy, which
41     // has a callback that takes an |int|. Both the name, and the value,
42     // must match what would appear in HIDL-generated code.
43     using startWithCallbackCopy_cb = std::function<void(int)>;
44 
45     // The callback type, for a method called startWithCallbackReference, which
46     // has a callback that takes an |int|. Both the name, and the value,
47     // must match what would appear in HIDL-generated code.
48     using startWithCallbackReference_cb = std::function<void(int)>;
49 
50     // Constants which allow tests to verify that the proxy methods can
51     // correctly return a value. We use different values for by-copy and
52     // by-reference, to double-check that a call was dispatched properly.
53     static constexpr int kByCopyResult = 42;
54     static constexpr int kByReferenceResult = 420;
55 
56     // Example of what a no-arg method would look like, if the callback
57     // is passed by-value.
startWithCallbackCopy(startWithCallbackCopy_cb _hidl_cb)58     ::android::hardware::Return<void> startWithCallbackCopy(
59         startWithCallbackCopy_cb _hidl_cb) {
60         _hidl_cb(kByCopyResult);
61         return ::android::hardware::Void();
62     }
63     // Example of what a no-arg method would look like, if the callback
64     // is passed by const-reference.
startWithCallbackReference(const startWithCallbackReference_cb & _hidl_cb)65     ::android::hardware::Return<void> startWithCallbackReference(
66         const startWithCallbackReference_cb& _hidl_cb) {
67         _hidl_cb(kByReferenceResult);
68         return ::android::hardware::Void();
69     }
70 };
71 
72 constexpr int IExample::kByCopyResult;
73 constexpr int IExample::kByReferenceResult;
74 }  // namespace
75 
76 static_assert(std::is_same<int, detail::functionArgSaver<
77                                     std::function<void(int)>>::StorageT>::value,
78               "Single-arg result should be stored directly.");
79 
80 static_assert(
81     std::is_same<std::pair<int, long>, detail::functionArgSaver<std::function<
82                                            void(int, long)>>::StorageT>::value,
83     "Two-arg result should be stored as a pair.");
84 
85 static_assert(
86     std::is_same<std::tuple<char, int, long>,
87                  detail::functionArgSaver<
88                      std::function<void(char, int, long)>>::StorageT>::value,
89     "Three-arg result should be stored as a tuple.");
90 
91 static_assert(std::is_same<Dummy, detail::functionArgSaver<std::function<
92                                       void(const Dummy&)>>::StorageT>::value,
93               "Reference should be stored by copy.");
94 
95 /*
96  * Verifies that HIDL_INVOKE can be used with methods that take the result
97  * callback as a by-value parameter. (This reflects the current implementation
98  * of HIDL-generated code.)
99  */
TEST(HidlInvokeTest,WorksWithMethodThatTakesResultCallbackByValue)100 TEST(HidlInvokeTest, WorksWithMethodThatTakesResultCallbackByValue) {
101     ::android::sp<IExample> sp = new IExample();
102     EXPECT_EQ(IExample::kByCopyResult, HIDL_INVOKE(sp, startWithCallbackCopy));
103 }
104 
105 /*
106  * Verifies that HIDL_INVOKE can be used with methods that take the result
107  * callback as a const-reference parameter. (This ensures that HIDL_INVOKE will
108  * continue to work, if the HIDL-generated code switches to const-ref.)
109  */
TEST(HidlInvokeTest,WorksWithMethodThatTakesResultCallbackByConstReference)110 TEST(HidlInvokeTest, WorksWithMethodThatTakesResultCallbackByConstReference) {
111     ::android::sp<IExample> sp = new IExample();
112     EXPECT_EQ(IExample::kByReferenceResult,
113               HIDL_INVOKE(sp, startWithCallbackReference));
114 }
115