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