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