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/aidl/TestStableLargeParcelable.h>
18 #include <aidl/aidl/TestStableLargeParcelableVector.h>
19 #include <aidl/aidl/TestStableParcelable.h>
20 #include <android/binder_auto_utils.h>
21 #include <android/binder_parcel.h>
22 #include <gtest/gtest.h>
23 
24 #include <LargeParcelable.h>
25 #include <LargeParcelableBase.h>
26 #include <LargeParcelableVector.h>
27 
28 #include <algorithm>
29 #include <vector>
30 
31 namespace {
32 
33 using ::aidl::aidl::TestStableLargeParcelable;
34 using ::aidl::aidl::TestStableLargeParcelableVector;
35 using ::aidl::aidl::TestStableParcelable;
36 using ::android::automotive::car_binder_lib::LargeParcelable;
37 using ::android::automotive::car_binder_lib::LargeParcelableBase;
38 using ::android::automotive::car_binder_lib::LargeParcelableVector;
39 using ::ndk::ScopedAParcel;
40 using ::ndk::ScopedFileDescriptor;
41 
42 int TEST_VALUE = 1234;
43 size_t VECTOR_SIZE = 16;
44 
createTestStableParcelable(size_t dataSize)45 std::unique_ptr<TestStableParcelable> createTestStableParcelable(size_t dataSize) {
46     std::unique_ptr<TestStableParcelable> p(new TestStableParcelable);
47     p->bytes.resize(dataSize);
48     std::fill(p->bytes.begin(), p->bytes.end(), 0x7f);
49     p->value = TEST_VALUE;
50     return p;
51 }
52 
createTestStableParcelableVector(size_t dataSize)53 std::vector<TestStableParcelable> createTestStableParcelableVector(size_t dataSize) {
54     std::vector<TestStableParcelable> p;
55     size_t VECTOR_SIZE = 16;
56     for (size_t i = 0; i < VECTOR_SIZE; i++) {
57         p.push_back(*createTestStableParcelable(dataSize / VECTOR_SIZE));
58     }
59     return p;
60 }
61 
checkTestStableParcelable(const TestStableParcelable * p,size_t dataSize)62 void checkTestStableParcelable(const TestStableParcelable* p, size_t dataSize) {
63     ASSERT_EQ(dataSize, p->bytes.size());
64     for (size_t i = 0; i < dataSize; i++) {
65         ASSERT_EQ(0x7f, p->bytes[i]);
66     }
67     ASSERT_EQ(TEST_VALUE, p->value);
68 }
69 
checkTestStableParcelableVector(const std::vector<TestStableParcelable> * p,size_t dataSize)70 void checkTestStableParcelableVector(const std::vector<TestStableParcelable>* p, size_t dataSize) {
71     ASSERT_EQ(VECTOR_SIZE, p->size());
72     for (size_t i = 0; i < VECTOR_SIZE; i++) {
73         checkTestStableParcelable(&((*p)[i]), dataSize / VECTOR_SIZE);
74     }
75 }
76 
testWrapStableAidlWriteReadPayload(size_t dataSize)77 void testWrapStableAidlWriteReadPayload(size_t dataSize) {
78     std::unique_ptr<TestStableParcelable> p = createTestStableParcelable(dataSize);
79 
80     LargeParcelable sendData(std::move(p));
81     ScopedAParcel parcel(AParcel_create());
82     binder_status_t status;
83     status = sendData.writeToParcel(parcel.get());
84 
85     ASSERT_EQ(status, STATUS_OK);
86 
87     // Set the parcel to start from 0 because we need to read from 0.
88     AParcel_setDataPosition(parcel.get(), 0);
89 
90     LargeParcelable<TestStableParcelable> receiveData;
91     status = receiveData.readFromParcel(parcel.get());
92 
93     ASSERT_EQ(status, STATUS_OK);
94 
95     ASSERT_TRUE(receiveData.getParcelable().has_value());
96 
97     const TestStableParcelable* getP = receiveData.getParcelable().value();
98 
99     checkTestStableParcelable(getP, dataSize);
100 }
101 
TEST(LargeParcelableTest,LargeParcelableWrapStableAidlWriteReadSmallPayload)102 TEST(LargeParcelableTest, LargeParcelableWrapStableAidlWriteReadSmallPayload) {
103     testWrapStableAidlWriteReadPayload(1024);
104 }
105 
TEST(LargeParcelableTest,LargeParcelableWrapStableAidlWriteReadLargePayload)106 TEST(LargeParcelableTest, LargeParcelableWrapStableAidlWriteReadLargePayload) {
107     testWrapStableAidlWriteReadPayload(8 * 1024);
108 }
109 
TEST(LargeParcelableTest,WrapStableAidlReuseSharedMemoryFile)110 TEST(LargeParcelableTest, WrapStableAidlReuseSharedMemoryFile) {
111     size_t dataSize = 8 * 1024;
112     std::unique_ptr<TestStableParcelable> p = createTestStableParcelable(dataSize);
113 
114     LargeParcelable sendData(std::move(p));
115 
116     ScopedAParcel parcel(AParcel_create());
117     binder_status_t status = sendData.writeToParcel(parcel.get());
118 
119     ASSERT_EQ(status, STATUS_OK);
120 
121     ScopedAParcel parcel2(AParcel_create());
122     status = sendData.writeToParcel(parcel2.get());
123 
124     ASSERT_EQ(status, STATUS_OK);
125 
126     // Set the parcel to start from 0 because we need to read from 0.
127     AParcel_setDataPosition(parcel2.get(), 0);
128 
129     LargeParcelable<TestStableParcelable> receiveData;
130     status = receiveData.readFromParcel(parcel2.get());
131 
132     ASSERT_EQ(status, STATUS_OK);
133 
134     ASSERT_TRUE(receiveData.getParcelable().has_value());
135     const TestStableParcelable* getP = receiveData.getParcelable().value();
136 
137     checkTestStableParcelable(getP, dataSize);
138 }
139 
testParcelableToStableLargeParcelable(size_t dataSize)140 void testParcelableToStableLargeParcelable(size_t dataSize) {
141     std::unique_ptr<TestStableParcelable> p = createTestStableParcelable(dataSize);
142 
143     TestStableLargeParcelable largeP;
144     largeP.payload = *p;
145     auto result = LargeParcelableBase::parcelableToStableLargeParcelable(largeP);
146 
147     ASSERT_TRUE(result.ok()) << result.error();
148 
149     TestStableLargeParcelable out;
150     if (result.value() == nullptr) {
151         out.payload = *p;
152     } else {
153         out.sharedMemoryFd = std::move(*result.value());
154     }
155 
156     ScopedAParcel parcel(AParcel_create());
157     binder_status_t status = out.writeToParcel(parcel.get());
158 
159     ASSERT_EQ(status, STATUS_OK);
160 
161     // Set the parcel to start from 0 because we need to read from 0.
162     AParcel_setDataPosition(parcel.get(), 0);
163 
164     // The parcel generated from StableLargeParcelable should be compatible with LargeParcelable.
165     // We use LargeParcelable based on TestStableParcelable to read from the generated parcel.
166     LargeParcelable<TestStableParcelable> receiveData;
167     status = receiveData.readFromParcel(parcel.get());
168 
169     ASSERT_EQ(status, STATUS_OK);
170 
171     ASSERT_TRUE(receiveData.getParcelable().has_value());
172     const TestStableParcelable* getP = receiveData.getParcelable().value();
173 
174     checkTestStableParcelable(getP, dataSize);
175 }
176 
TEST(LargeParcelableTest,ParcelableToStableLargeParcelableSmallPayload)177 TEST(LargeParcelableTest, ParcelableToStableLargeParcelableSmallPayload) {
178     testParcelableToStableLargeParcelable(1024);
179 }
180 
TEST(LargeParcelableTest,ParcelableToStableLargeParcelableLargePayload)181 TEST(LargeParcelableTest, ParcelableToStableLargeParcelableLargePayload) {
182     testParcelableToStableLargeParcelable(8 * 1024);
183 }
184 
testStableLargeParcelableToParcelable(size_t dataSize)185 void testStableLargeParcelableToParcelable(size_t dataSize) {
186     std::unique_ptr<TestStableParcelable> p = createTestStableParcelable(dataSize);
187 
188     // Use LargeParcelable to write to a parcel. Since it is compatible with StableLargeParcelable,
189     // it should be able to be parsed.
190     LargeParcelable sendData(std::move(p));
191     ScopedAParcel parcel(AParcel_create());
192     binder_status_t status;
193     status = sendData.writeToParcel(parcel.get());
194 
195     ASSERT_EQ(status, STATUS_OK);
196 
197     // Set the parcel to start from 0 because we need to read from 0.
198     AParcel_setDataPosition(parcel.get(), 0);
199 
200     TestStableLargeParcelable largeParcelable;
201     status = largeParcelable.readFromParcel(parcel.get());
202 
203     ASSERT_EQ(status, STATUS_OK);
204 
205     // Convert the StableLargeParcelable back to the original parcelable.
206     auto result = LargeParcelableBase::stableLargeParcelableToParcelable(largeParcelable);
207 
208     ASSERT_TRUE(result.ok()) << result.error();
209 
210     const TestStableLargeParcelable* out = result.value().getObject();
211     ASSERT_TRUE(out->payload.has_value());
212     checkTestStableParcelable(&(out->payload.value()), dataSize);
213 }
214 
TEST(LargeParcelableTest,StableLargeParcelableToParcelableSmallPayload)215 TEST(LargeParcelableTest, StableLargeParcelableToParcelableSmallPayload) {
216     testStableLargeParcelableToParcelable(1024);
217 }
218 
TEST(LargeParcelableTest,StableLargeParcelableToParcelableLargePayload)219 TEST(LargeParcelableTest, StableLargeParcelableToParcelableLargePayload) {
220     testStableLargeParcelableToParcelable(8 * 1024);
221 }
222 
testParcelableToStableLargeParcelableBackToParcelable(size_t dataSize)223 void testParcelableToStableLargeParcelableBackToParcelable(size_t dataSize) {
224     std::unique_ptr<TestStableParcelable> p = createTestStableParcelable(dataSize);
225 
226     TestStableLargeParcelable largeP;
227     largeP.payload = *p;
228     auto result1 = LargeParcelableBase::parcelableToStableLargeParcelable(largeP);
229 
230     ASSERT_TRUE(result1.ok()) << result1.error();
231 
232     TestStableLargeParcelable intermediate;
233     if (result1.value() == nullptr) {
234         intermediate.payload = std::move(*p);
235     } else {
236         intermediate.sharedMemoryFd = std::move(*result1.value());
237     }
238 
239     auto result2 = LargeParcelableBase::stableLargeParcelableToParcelable(intermediate);
240 
241     ASSERT_TRUE(result2.ok()) << result2.error();
242 
243     const TestStableLargeParcelable* out = result2.value().getObject();
244     ASSERT_TRUE(out->payload.has_value());
245     checkTestStableParcelable(&(out->payload.value()), dataSize);
246 }
247 
TEST(LargeParcelableTest,ParcelableToStableLargeParcelableBackToParcelableSmallPayload)248 TEST(LargeParcelableTest, ParcelableToStableLargeParcelableBackToParcelableSmallPayload) {
249     testParcelableToStableLargeParcelableBackToParcelable(1024);
250 }
251 
TEST(LargeParcelableTest,ParcelableToStableLargeParcelableBackToParcelableLargePayload)252 TEST(LargeParcelableTest, ParcelableToStableLargeParcelableBackToParcelableLargePayload) {
253     testParcelableToStableLargeParcelableBackToParcelable(8 * 1024);
254 }
255 
testWrapStableAidlVectorWriteReadPayload(size_t dataSize)256 void testWrapStableAidlVectorWriteReadPayload(size_t dataSize) {
257     std::vector<TestStableParcelable> p = createTestStableParcelableVector(dataSize);
258 
259     LargeParcelableVector sendData(std::move(p));
260     ScopedAParcel parcel(AParcel_create());
261     binder_status_t status;
262     status = sendData.writeToParcel(parcel.get());
263 
264     ASSERT_EQ(status, STATUS_OK);
265 
266     // Set the parcel to start from 0 because we need to read from 0.
267     AParcel_setDataPosition(parcel.get(), 0);
268 
269     LargeParcelableVector<TestStableParcelable> receiveData;
270     status = receiveData.readFromParcel(parcel.get());
271 
272     ASSERT_EQ(status, STATUS_OK);
273 
274     ASSERT_TRUE(receiveData.getParcelables().has_value());
275     const std::vector<TestStableParcelable>* getP = receiveData.getParcelables().value();
276 
277     checkTestStableParcelableVector(getP, dataSize);
278 }
279 
TEST(LargeParcelableTest,LargeParcelableWrapStableAidlVectorWriteReadSmallPayload)280 TEST(LargeParcelableTest, LargeParcelableWrapStableAidlVectorWriteReadSmallPayload) {
281     testWrapStableAidlVectorWriteReadPayload(1024);
282 }
283 
TEST(LargeParcelableTest,LargeParcelableWrapStableAidlVectorWriteReadLargePayload)284 TEST(LargeParcelableTest, LargeParcelableWrapStableAidlVectorWriteReadLargePayload) {
285     testWrapStableAidlVectorWriteReadPayload(8 * 1024);
286 }
287 
testParcelableVectorToStableLargeParcelable(size_t dataSize)288 void testParcelableVectorToStableLargeParcelable(size_t dataSize) {
289     std::vector<TestStableParcelable> p = createTestStableParcelableVector(dataSize);
290     TestStableLargeParcelableVector largeP;
291     largeP.payload = p;
292 
293     auto result = LargeParcelableBase::parcelableToStableLargeParcelable(largeP);
294 
295     ASSERT_TRUE(result.ok()) << result.error();
296 
297     TestStableLargeParcelableVector out;
298     if (result.value() == nullptr) {
299         out.payload = std::move(p);
300     } else {
301         out.sharedMemoryFd = std::move(*result.value());
302     }
303 
304     ScopedAParcel parcel(AParcel_create());
305     binder_status_t status = out.writeToParcel(parcel.get());
306 
307     ASSERT_EQ(status, STATUS_OK);
308 
309     // Set the parcel to start from 0 because we need to read from 0.
310     AParcel_setDataPosition(parcel.get(), 0);
311 
312     // The parcel generated from StableLargeParcelable should be compatible with LargeParcelable.
313     // We use LargeParcelable based on TestStableParcelable to read from the generated parcel.
314     LargeParcelableVector<TestStableParcelable> receiveData;
315     status = receiveData.readFromParcel(parcel.get());
316 
317     ASSERT_EQ(status, STATUS_OK);
318 
319     ASSERT_TRUE(receiveData.getParcelables().has_value());
320     const std::vector<TestStableParcelable>* getP = receiveData.getParcelables().value();
321 
322     checkTestStableParcelableVector(getP, dataSize);
323 }
324 
TEST(LargeParcelableTest,ParcelableVectorToStableLargeParcelableSmallPayload)325 TEST(LargeParcelableTest, ParcelableVectorToStableLargeParcelableSmallPayload) {
326     testParcelableVectorToStableLargeParcelable(1024);
327 }
328 
TEST(LargeParcelableTest,ParcelableVectorToStableLargeParcelableLargePayload)329 TEST(LargeParcelableTest, ParcelableVectorToStableLargeParcelableLargePayload) {
330     testParcelableVectorToStableLargeParcelable(8 * 1024);
331 }
332 
testStableLargeParcelableToParcelableVector(size_t dataSize)333 void testStableLargeParcelableToParcelableVector(size_t dataSize) {
334     std::vector<TestStableParcelable> p = createTestStableParcelableVector(dataSize);
335 
336     // Use LargeParcelable to write to a parcel. Since it is compatible with StableLargeParcelable,
337     // it should be able to be parsed.
338     LargeParcelableVector sendData(std::move(p));
339     ScopedAParcel parcel(AParcel_create());
340     binder_status_t status;
341     status = sendData.writeToParcel(parcel.get());
342 
343     ASSERT_EQ(status, STATUS_OK);
344 
345     // Set the parcel to start from 0 because we need to read from 0.
346     AParcel_setDataPosition(parcel.get(), 0);
347 
348     TestStableLargeParcelableVector largeParcelable;
349     status = largeParcelable.readFromParcel(parcel.get());
350 
351     ASSERT_EQ(status, STATUS_OK);
352 
353     std::vector<TestStableParcelable> out;
354     // Convert the StableLargeParcelable back to the original parcelable.
355     auto result = LargeParcelableBase::stableLargeParcelableToParcelable(largeParcelable);
356 
357     ASSERT_TRUE(result.ok()) << result.error();
358 
359     checkTestStableParcelableVector(&(result.value().getObject()->payload), dataSize);
360 }
361 
TEST(LargeParcelableTest,StableLargeParcelableToParcelableVectorSmallPayload)362 TEST(LargeParcelableTest, StableLargeParcelableToParcelableVectorSmallPayload) {
363     testStableLargeParcelableToParcelableVector(1024);
364 }
365 
TEST(LargeParcelableTest,StableLargeParcelableToParcelableVectorLargePayload)366 TEST(LargeParcelableTest, StableLargeParcelableToParcelableVectorLargePayload) {
367     testStableLargeParcelableToParcelableVector(8 * 1024);
368 }
369 
testParcelableVectorToStableLargeParcelableBackToParcelableVector(size_t dataSize)370 void testParcelableVectorToStableLargeParcelableBackToParcelableVector(size_t dataSize) {
371     std::vector<TestStableParcelable> p = createTestStableParcelableVector(dataSize);
372     TestStableLargeParcelableVector largeP;
373     largeP.payload = p;
374 
375     auto result1 = LargeParcelableBase::parcelableToStableLargeParcelable(largeP);
376 
377     ASSERT_TRUE(result1.ok()) << result1.error();
378 
379     TestStableLargeParcelableVector intermediate;
380     if (result1.value() == nullptr) {
381         intermediate.payload = std::move(p);
382     } else {
383         intermediate.sharedMemoryFd = std::move(*result1.value());
384     }
385 
386     auto result2 = LargeParcelableBase::stableLargeParcelableToParcelable(intermediate);
387 
388     ASSERT_TRUE(result2.ok()) << result2.error();
389 
390     checkTestStableParcelableVector(&(result2.value().getObject()->payload), dataSize);
391 }
392 
TEST(LargeParcelableTest,ParcelableVectorToStableLargeParcelableBackToParcelableVectorSmallPayload)393 TEST(LargeParcelableTest,
394      ParcelableVectorToStableLargeParcelableBackToParcelableVectorSmallPayload) {
395     testParcelableVectorToStableLargeParcelableBackToParcelableVector(1024);
396 }
397 
TEST(LargeParcelableTest,ParcelableVectorToStableLargeParcelableBackToParcelableVectorLargePayload)398 TEST(LargeParcelableTest,
399      ParcelableVectorToStableLargeParcelableBackToParcelableVectorLargePayload) {
400     testParcelableVectorToStableLargeParcelableBackToParcelableVector(8 * 1024);
401 }
402 
403 }  //  namespace
404