1 /*
2 * Copyright (C) 2021 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 <aidl/android/aidl/loggable/ILoggableInterface.h>
18
19 #include <functional>
20
21 #include <android/binder_auto_utils.h>
22 #include <android/binder_manager.h>
23 #include <binder/ProcessState.h>
24 #include <gtest/gtest.h>
25
26 #include <aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h>
27 #include <aidl/android/aidl/tests/ITestService.h>
28 #include <aidl/android/aidl/tests/RecursiveList.h>
29 #include <aidl/android/aidl/tests/Union.h>
30 #include <aidl/android/aidl/tests/extension/MyExt.h>
31 #include <aidl/android/aidl/tests/vintf/VintfExtendableParcelable.h>
32 #include <aidl/android/aidl/tests/vintf/VintfParcelable.h>
33
34 using aidl::android::aidl::fixedsizearray::FixedSizeArrayExample;
35 using BnRepeatFixedSizeArray =
36 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnRepeatFixedSizeArray;
37 using BpRepeatFixedSizeArray =
38 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BpRepeatFixedSizeArray;
39 using IntParcelable = aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable;
40 using IRepeatFixedSizeArray =
41 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IRepeatFixedSizeArray;
42 using BnEmptyInterface =
43 aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnEmptyInterface;
44 using aidl::android::aidl::tests::BackendType;
45 using aidl::android::aidl::tests::ITestService;
46 using aidl::android::aidl::tests::RecursiveList;
47 using aidl::android::aidl::tests::SimpleParcelable;
48 using aidl::android::aidl::tests::Union;
49 using aidl::android::aidl::tests::extension::ExtendableParcelable;
50 using aidl::android::aidl::tests::extension::MyExt;
51 using aidl::android::aidl::tests::vintf::VintfExtendableParcelable;
52 using aidl::android::aidl::tests::vintf::VintfParcelable;
53 using android::OK;
54 using ndk::AParcel_readData;
55 using ndk::AParcel_writeData;
56 using ndk::ScopedAStatus;
57 using ndk::SharedRefBase;
58 using ndk::SpAIBinder;
59
60 struct AidlTest : testing::Test {
61 template <typename T>
getServiceAidlTest62 std::shared_ptr<T> getService() {
63 android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
64 android::ProcessState::self()->startThreadPool();
65 ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_waitForService(T::descriptor));
66 return T::fromBinder(binder);
67 }
68 };
69
70 // TODO(b/196454897): copy more tests from aidl_test_client
71
TEST_F(AidlTest,RepeatSimpleParcelable)72 TEST_F(AidlTest, RepeatSimpleParcelable) {
73 SimpleParcelable input("foo", 42);
74 SimpleParcelable out_param, returned;
75 auto status = getService<ITestService>()->RepeatSimpleParcelable(input, &out_param, &returned);
76 ASSERT_TRUE(status.isOk());
77 EXPECT_EQ(input, out_param) << input.toString() << " " << out_param.toString();
78 EXPECT_EQ(input, returned) << input.toString() << " " << returned.toString();
79 }
80
TEST_F(AidlTest,ReverseSimpleParcelable)81 TEST_F(AidlTest, ReverseSimpleParcelable) {
82 BackendType backend;
83 auto status = getService<ITestService>()->getBackendType(&backend);
84 ASSERT_TRUE(status.isOk());
85
86 const std::vector<SimpleParcelable> original{SimpleParcelable("a", 1), SimpleParcelable("b", 2),
87 SimpleParcelable("c", 3)};
88 std::vector<SimpleParcelable> repeated;
89 if (backend == BackendType::JAVA) {
90 repeated = std::vector<SimpleParcelable>(original.size());
91 }
92 std::vector<SimpleParcelable> reversed;
93 status = getService<ITestService>()->ReverseSimpleParcelables(original, &repeated, &reversed);
94 ASSERT_TRUE(status.isOk());
95
96 EXPECT_EQ(repeated, original);
97
98 std::reverse(reversed.begin(), reversed.end());
99 EXPECT_EQ(reversed, original);
100 }
101
TEST_F(AidlTest,ReverseRecursiveList)102 TEST_F(AidlTest, ReverseRecursiveList) {
103 std::unique_ptr<RecursiveList> head;
104 for (int i = 0; i < 10; i++) {
105 auto node = std::make_unique<RecursiveList>();
106 node->value = i;
107 node->next = std::move(head);
108 head = std::move(node);
109 }
110 // head: [9, 8, ... 0]
111
112 RecursiveList reversed;
113 auto status = getService<ITestService>()->ReverseList(*head, &reversed);
114 ASSERT_TRUE(status.isOk());
115
116 // reversed should be [0, 1, .. 9]
117 RecursiveList* cur = &reversed;
118 for (int i = 0; i < 10; i++) {
119 EXPECT_EQ(i, cur->value);
120 cur = cur->next.get();
121 }
122 EXPECT_EQ(nullptr, cur);
123 }
124
TEST_F(AidlTest,RepeatExtendableParcelable)125 TEST_F(AidlTest, RepeatExtendableParcelable) {
126 MyExt ext;
127 ext.a = 42;
128 ext.b = "EXT";
129 ExtendableParcelable ep;
130 ep.a = 1;
131 ep.b = "a";
132 ep.ext.setParcelable(ext);
133
134 ExtendableParcelable ep2;
135 auto status = getService<ITestService>()->RepeatExtendableParcelable(ep, &ep2);
136 ASSERT_TRUE(status.isOk()) << status.getDescription();
137
138 EXPECT_EQ(ep2.a, ep.a);
139 EXPECT_EQ(ep2.b, ep.b);
140
141 std::optional<MyExt> ret_ext;
142 ASSERT_EQ(ep2.ext.getParcelable(&ret_ext), OK);
143 ASSERT_TRUE(ret_ext.has_value());
144
145 EXPECT_EQ(ret_ext->a, ext.a);
146 EXPECT_EQ(ret_ext->b, ext.b);
147 }
148
TEST_F(AidlTest,RepeatExtendableParcelableVintf)149 TEST_F(AidlTest, RepeatExtendableParcelableVintf) {
150 VintfParcelable inner;
151 inner.a = 5;
152
153 VintfExtendableParcelable ext;
154 ext.ext.setParcelable(inner);
155
156 ExtendableParcelable ep;
157 ep.a = 1;
158 ep.b = "a";
159 ep.ext.setParcelable(ext);
160
161 ExtendableParcelable ep2;
162 auto status = getService<ITestService>()->RepeatExtendableParcelableVintf(ep, &ep2);
163 ASSERT_TRUE(status.isOk()) << status.getDescription();
164
165 EXPECT_EQ(ep2.a, ep.a);
166 EXPECT_EQ(ep2.b, ep.b);
167
168 std::optional<VintfExtendableParcelable> ret_ext;
169 ASSERT_EQ(ep2.ext.getParcelable(&ret_ext), OK);
170 ASSERT_TRUE(ret_ext.has_value());
171
172 std::optional<VintfParcelable> ret_inner;
173 ASSERT_EQ(ret_ext->ext.getParcelable(&ret_inner), OK);
174 ASSERT_TRUE(ret_inner.has_value());
175 EXPECT_EQ(ret_inner->a, inner.a);
176 }
177
TEST_F(AidlTest,GetUnionTags)178 TEST_F(AidlTest, GetUnionTags) {
179 std::vector<Union> unions;
180 std::vector<Union::Tag> tags;
181 // test empty
182 auto status = getService<ITestService>()->GetUnionTags(unions, &tags);
183 ASSERT_TRUE(status.isOk());
184 EXPECT_EQ(tags, (std::vector<Union::Tag>{}));
185 // test non-empty
186 unions.push_back(Union::make<Union::n>());
187 unions.push_back(Union::make<Union::ns>());
188 status = getService<ITestService>()->GetUnionTags(unions, &tags);
189 ASSERT_TRUE(status.isOk());
190 EXPECT_EQ(tags, (std::vector<Union::Tag>{Union::n, Union::ns}));
191 }
192
TEST_F(AidlTest,FixedSizeArray)193 TEST_F(AidlTest, FixedSizeArray) {
194 auto parcel = AParcel_create();
195
196 FixedSizeArrayExample p;
197 p.byteMatrix[0][0] = 0;
198 p.byteMatrix[0][1] = 1;
199 p.byteMatrix[1][0] = 2;
200 p.byteMatrix[1][1] = 3;
201 p.floatMatrix[0][0] = 0.f;
202 p.floatMatrix[0][1] = 1.f;
203 p.floatMatrix[1][0] = 2.f;
204 p.floatMatrix[1][1] = 3.f;
205 EXPECT_EQ(OK, p.writeToParcel(parcel));
206
207 AParcel_setDataPosition(parcel, 0);
208
209 FixedSizeArrayExample q;
210 EXPECT_EQ(OK, q.readFromParcel(parcel));
211 EXPECT_EQ(p, q);
212
213 AParcel_delete(parcel);
214 }
215
TEST_F(AidlTest,FixedSizeArrayWithValuesAtNullableFields)216 TEST_F(AidlTest, FixedSizeArrayWithValuesAtNullableFields) {
217 auto parcel = AParcel_create();
218
219 FixedSizeArrayExample p;
220 p.boolNullableArray = std::array<bool, 2>{true, false};
221 p.byteNullableArray = std::array<uint8_t, 2>{42, 0};
222 p.stringNullableArray = std::array<std::optional<std::string>, 2>{"hello", "world"};
223
224 p.boolNullableMatrix.emplace();
225 p.boolNullableMatrix->at(0) = std::array<bool, 2>{true, false};
226 p.byteNullableMatrix.emplace();
227 p.byteNullableMatrix->at(0) = std::array<uint8_t, 2>{42, 0};
228 p.stringNullableMatrix.emplace();
229 p.stringNullableMatrix->at(0) = std::array<std::optional<std::string>, 2>{"hello", "world"};
230
231 EXPECT_EQ(OK, p.writeToParcel(parcel));
232
233 AParcel_setDataPosition(parcel, 0);
234
235 FixedSizeArrayExample q;
236 EXPECT_EQ(OK, q.readFromParcel(parcel));
237 EXPECT_EQ(p, q);
238
239 AParcel_delete(parcel);
240 }
241
TEST_F(AidlTest,FixedSizeArrayOfBytesShouldBePacked)242 TEST_F(AidlTest, FixedSizeArrayOfBytesShouldBePacked) {
243 auto parcel = AParcel_create();
244
245 std::array<std::array<uint8_t, 3>, 2> byte_array;
246 byte_array[0] = {1, 2, 3};
247 byte_array[1] = {4, 5, 6};
248 EXPECT_EQ(OK, AParcel_writeData(parcel, byte_array));
249
250 AParcel_setDataPosition(parcel, 0);
251
252 int32_t len;
253 EXPECT_EQ(OK, AParcel_readData(parcel, &len));
254 EXPECT_EQ(2, len);
255 std::vector<uint8_t> byte_vector;
256 EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
257 EXPECT_EQ(byte_vector, (std::vector<uint8_t>{1, 2, 3}));
258 EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
259 EXPECT_EQ(byte_vector, (std::vector<uint8_t>{4, 5, 6}));
260
261 AParcel_delete(parcel);
262 }
263
264 template <typename Service, typename MemFn, typename Input>
CheckRepeat(Service service,MemFn fn,Input input)265 void CheckRepeat(Service service, MemFn fn, Input input) {
266 Input out1, out2;
267 EXPECT_TRUE(std::invoke(fn, service, input, &out1, &out2).isOk());
268 EXPECT_EQ(input, out1);
269 EXPECT_EQ(input, out2);
270 }
271
272 template <typename T>
Make2dArray(std::initializer_list<T> values)273 std::array<std::array<T, 3>, 2> Make2dArray(std::initializer_list<T> values) {
274 std::array<std::array<T, 3>, 2> arr = {};
275 auto it = std::begin(values);
276 for (auto& row : arr) {
277 for (auto& el : row) {
278 if (it == std::end(values)) break;
279 el = *it++;
280 }
281 }
282 return arr;
283 }
284
TEST_F(AidlTest,FixedSizeArrayOverBinder)285 TEST_F(AidlTest, FixedSizeArrayOverBinder) {
286 auto service = getService<IRepeatFixedSizeArray>();
287
288 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBytes, (std::array<uint8_t, 3>{1, 2, 3}));
289
290 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatInts, (std::array<int32_t, 3>{1, 2, 3}));
291
292 auto binder1 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
293 auto binder2 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
294 auto binder3 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
295 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBinders,
296 (std::array<SpAIBinder, 3>{binder1, binder2, binder3}));
297
298 IntParcelable p1, p2, p3;
299 p1.value = 1;
300 p2.value = 2;
301 p3.value = 3;
302 CheckRepeat(service, &IRepeatFixedSizeArray::RepeatParcelables,
303 (std::array<IntParcelable, 3>{p1, p2, p3}));
304
305 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBytes, Make2dArray<uint8_t>({1, 2, 3}));
306
307 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dInts, Make2dArray<int32_t>({1, 2, 3}));
308
309 // Not-nullable
310 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBinders,
311 Make2dArray<SpAIBinder>({binder1, binder2, binder3, binder1, binder2, binder3}));
312
313 CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dParcelables,
314 Make2dArray<IntParcelable>({p1, p2, p3}));
315 }
316