xref: /aosp_15_r20/cts/tests/tests/binder_ndk/libbinder_ndk_test/test_parcel.cpp (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2018 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 #define LOG_TAG "Cts-NdkBinderTest"
17 
18 #include <android/binder_ibinder.h>
19 #include <android/binder_parcel.h>
20 #include <android/binder_parcel_utils.h>
21 #include <android/log.h>
22 #include <gtest/gtest.h>
23 
24 #include "utilities.h"
25 
26 #include <limits>
27 #include <vector>
28 
29 class NdkBinderTest_AParcel : public NdkBinderTest {};
30 
31 template <typename T, typename Enable = void>
32 struct WriteFrom {
33   using type = const T;
34 };
35 template <>
36 struct WriteFrom<AStatus*> {
37   // not 'const T' = 'AStatus* const' where T = AStatus*.
38   using type = const AStatus*;
39 };
40 
41 template <typename T>
NdkBinderSenseOfEquality(T a,T b)42 bool NdkBinderSenseOfEquality(T a, T b) {
43   return a == b;
44 }
45 template <>
NdkBinderSenseOfEquality(const AStatus * a,const AStatus * b)46 bool NdkBinderSenseOfEquality<const AStatus*>(const AStatus* a,
47                                               const AStatus* b) {
48   if (a == b) return true;
49 
50   return AStatus_isOk(a) == AStatus_isOk(b) &&
51          AStatus_getExceptionCode(a) == AStatus_getExceptionCode(b) &&
52          AStatus_getServiceSpecificError(a) ==
53              AStatus_getServiceSpecificError(b) &&
54          AStatus_getStatus(a) == AStatus_getStatus(b) &&
55          std::string(AStatus_getMessage(a)) == AStatus_getMessage(b);
56 }
57 template <>
NdkBinderSenseOfEquality(AStatus * a,AStatus * b)58 bool NdkBinderSenseOfEquality<AStatus*>(AStatus* a, AStatus* b) {
59   return NdkBinderSenseOfEquality<const AStatus*>(a, b);
60 }
61 
62 template <typename T>
castForStream(T val)63 auto castForStream(T val) {
64   return val;
65 }
66 
67 template <>
castForStream(char16_t val)68 auto castForStream(char16_t val) {
69   return static_cast<int>(val);
70 }
71 
72 // These reads and writes an array of possible values all of the same type.
73 template <typename T,
74           binder_status_t (*write)(AParcel*, typename WriteFrom<T>::type),
75           binder_status_t (*read)(const AParcel*, T*)>
ExpectInOut(std::vector<T> in)76 void ExpectInOut(std::vector<T> in) {
77   AIBinder* binder = SampleData::newBinder(
78       [](transaction_code_t, const AParcel* in, AParcel* out) {
79         T readTarget = {};
80         EXPECT_OK(read(in, &readTarget));
81         EXPECT_OK(write(out, readTarget));
82         return STATUS_OK;
83       },
84       ExpectLifetimeTransactions(in.size()));
85 
86   for (const auto& value : in) {
87     EXPECT_OK(SampleData::transact(
88         binder, kCode,
89         [&](AParcel* in) {
90           EXPECT_OK(write(in, value));
91           return STATUS_OK;
92         },
93         [&](const AParcel* out) {
94           T readTarget = {};
95           EXPECT_OK(read(out, &readTarget));
96           EXPECT_TRUE(NdkBinderSenseOfEquality<T>(value, readTarget))
97               << castForStream(value) << " is not " << castForStream(readTarget);
98           return STATUS_OK;
99         }));
100   }
101 
102   AIBinder_decStrong(binder);
103 }
104 
105 template <typename T,
106           binder_status_t (*write)(AParcel*, typename WriteFrom<T>::type),
107           binder_status_t (*read)(const AParcel*, T*)>
ExpectInOutMinMax()108 void ExpectInOutMinMax() {
109   ExpectInOut<T, write, read>(
110       {std::numeric_limits<T>::min(), std::numeric_limits<T>::max()});
111 }
112 
TEST_F(NdkBinderTest_AParcel,BindersInMustComeOut)113 TEST_F(NdkBinderTest_AParcel, BindersInMustComeOut) {
114   AIBinder* binder = SampleData::newBinder();
115 
116   ExpectInOut<AIBinder*, AParcel_writeStrongBinder, AParcel_readStrongBinder>(
117       {binder});
118   // copy which is read when this binder is sent in a transaction to this
119   // process
120   AIBinder_decStrong(binder);
121   // copy which is read when this binder is returned in a transaction within
122   // this same process and is read again
123   AIBinder_decStrong(binder);
124 
125   ExpectInOut<AIBinder*, AParcel_writeStrongBinder, AParcel_readStrongBinder>(
126       {nullptr, binder});
127   // copy which is read when this binder is sent in a transaction to this
128   // process
129   AIBinder_decStrong(binder);
130   // copy which is read when this binder is returned in a transaction within
131   // this same process and is read again
132   AIBinder_decStrong(binder);
133 
134   AIBinder_decStrong(binder);
135 }
136 
TEST_F(NdkBinderTest_AParcel,StatusesInMustComeOut)137 TEST_F(NdkBinderTest_AParcel, StatusesInMustComeOut) {
138   // This does not clean up status objects.
139   ExpectInOut<AStatus*, AParcel_writeStatusHeader, AParcel_readStatusHeader>({
140       AStatus_newOk(),
141       AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT),
142       AStatus_fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
143                                            "+++++++++[->++++++++<]>.+."),
144       AStatus_fromServiceSpecificError(1776),
145       AStatus_fromServiceSpecificErrorWithMessage(0xBEA, "utiful!"),
146   });
147 }
148 
TEST_F(NdkBinderTest_AParcel,LowLevelErrorsHaveNoStatusHeader)149 TEST_F(NdkBinderTest_AParcel, LowLevelErrorsHaveNoStatusHeader) {
150   AIBinder* binder =
151       SampleData::newBinder(nullptr, ExpectLifetimeTransactions(0));
152 
153   EXPECT_EQ(
154       STATUS_UNKNOWN_ERROR,
155       SampleData::transact(binder, kCode, [&](AParcel* in) {
156         AStatus* status = nullptr;
157 
158         status = AStatus_fromExceptionCode(EX_TRANSACTION_FAILED);
159         EXPECT_EQ(STATUS_FAILED_TRANSACTION,
160                   AParcel_writeStatusHeader(in, status));
161         AStatus_delete(status);
162 
163         status = AStatus_fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED,
164                                                       "something or other");
165         EXPECT_EQ(STATUS_FAILED_TRANSACTION,
166                   AParcel_writeStatusHeader(in, status));
167         AStatus_delete(status);
168 
169         status = AStatus_fromStatus(STATUS_UNKNOWN_ERROR);
170         EXPECT_EQ(STATUS_UNKNOWN_ERROR, AParcel_writeStatusHeader(in, status));
171         AStatus_delete(status);
172 
173         status = AStatus_fromStatus(STATUS_BAD_VALUE);
174         EXPECT_EQ(STATUS_BAD_VALUE, AParcel_writeStatusHeader(in, status));
175         AStatus_delete(status);
176 
177         return STATUS_UNKNOWN_ERROR;
178       }));
179 
180   AIBinder_decStrong(binder);
181 }
182 
TEST_F(NdkBinderTest_AParcel,WhatGoesInMustComeOut)183 TEST_F(NdkBinderTest_AParcel, WhatGoesInMustComeOut) {
184   ExpectInOut<int32_t, AParcel_writeInt32, AParcel_readInt32>(
185       {-7, -1, 0, 1, 45});
186   ExpectInOut<uint32_t, AParcel_writeUint32, AParcel_readUint32>(
187       {0, 1, 2, 100});
188   ExpectInOut<int64_t, AParcel_writeInt64, AParcel_readInt64>(
189       {-7, -1, 0, 1, 45});
190   ExpectInOut<uint64_t, AParcel_writeUint64, AParcel_readUint64>(
191       {0, 1, 2, 100});
192   ExpectInOut<float, AParcel_writeFloat, AParcel_readFloat>(
193       {-1.0f, 0.0f, 1.0f, 0.24975586f, 0.3f});
194   ExpectInOut<double, AParcel_writeDouble, AParcel_readDouble>(
195       {-1.0, 0.0, 1.0, 0.24975586, 0.3});
196 
197   ExpectInOut<bool, AParcel_writeBool, AParcel_readBool>({true, false});
198   ExpectInOut<char16_t, AParcel_writeChar, AParcel_readChar>(
199       {L'\0', L'S', L'@', L'\n'});
200   ExpectInOut<int8_t, AParcel_writeByte, AParcel_readByte>({-7, -1, 0, 1, 45});
201 }
202 
TEST_F(NdkBinderTest_AParcel,ExtremeValues)203 TEST_F(NdkBinderTest_AParcel, ExtremeValues) {
204   ExpectInOutMinMax<int32_t, AParcel_writeInt32, AParcel_readInt32>();
205   ExpectInOutMinMax<uint32_t, AParcel_writeUint32, AParcel_readUint32>();
206   ExpectInOutMinMax<int64_t, AParcel_writeInt64, AParcel_readInt64>();
207   ExpectInOutMinMax<uint64_t, AParcel_writeUint64, AParcel_readUint64>();
208   ExpectInOutMinMax<float, AParcel_writeFloat, AParcel_readFloat>();
209   ExpectInOutMinMax<double, AParcel_writeDouble, AParcel_readDouble>();
210   ExpectInOutMinMax<bool, AParcel_writeBool, AParcel_readBool>();
211   ExpectInOutMinMax<char16_t, AParcel_writeChar, AParcel_readChar>();
212   ExpectInOutMinMax<int8_t, AParcel_writeByte, AParcel_readByte>();
213 }
214 
TEST_F(NdkBinderTest_AParcel,NonNullTerminatedString)215 TEST_F(NdkBinderTest_AParcel, NonNullTerminatedString) {
216   // This is a helper to write a vector of strings which are not
217   // null-terminated. It has infinite length, and every element is the same
218   // value (element.substr(0, elementLen)). However, when it is written, no
219   // copies of element are made to produce a null-terminated string.
220   struct PartialStringCycle {
221     // every element of the vector is a prefix of this string
222     const std::string& element;
223     // this is the number of characters of the string to write, < element.size()
224     int32_t elementLen;
225 
226     binder_status_t writeToParcel(AParcel* p, size_t length) const {
227       return AParcel_writeStringArray(p, static_cast<const void*>(this), length,
228                                       ElementGetter);
229     }
230 
231    private:
232     static const char* ElementGetter(const void* vectorData, size_t /*index*/, int32_t* outLength) {
233       const PartialStringCycle* vector =
234           static_cast<const PartialStringCycle*>(vectorData);
235 
236       *outLength = vector->elementLen;
237       return vector->element.c_str();
238     }
239   };
240 
241   const std::string kTestcase = "aoeuhtns";
242 
243   for (size_t i = 0; i < kTestcase.size(); i++) {
244     const std::string expectedString = kTestcase.substr(0, i);
245     const std::vector<std::string> expectedVector = {expectedString,
246                                                      expectedString};
247 
248     const PartialStringCycle writeVector{.element = kTestcase,
249                                          .elementLen = static_cast<int32_t>(i)};
250 
251     AIBinder* binder = SampleData::newBinder(
252         [&](transaction_code_t, const AParcel* in, AParcel* /*out*/) {
253           std::string readString;
254           EXPECT_OK(::ndk::AParcel_readString(in, &readString));
255           EXPECT_EQ(expectedString, readString);
256 
257           std::vector<std::string> readVector;
258           EXPECT_OK(::ndk::AParcel_readVector(in, &readVector));
259           EXPECT_EQ(expectedVector, readVector);
260 
261           return STATUS_OK;
262         },
263         ExpectLifetimeTransactions(1));
264 
265     EXPECT_OK(SampleData::transact(
266         binder, kCode,
267         [&](AParcel* in) {
268           EXPECT_OK(AParcel_writeString(in, kTestcase.c_str(), i));
269           EXPECT_OK(writeVector.writeToParcel(in, expectedVector.size()));
270           return STATUS_OK;
271         },
272         ReadNothingFromParcel));
273 
274     AIBinder_decStrong(binder);
275   }
276 }
277 
TEST_F(NdkBinderTest_AParcel,CantReadFromEmptyParcel)278 TEST_F(NdkBinderTest_AParcel, CantReadFromEmptyParcel) {
279   AIBinder* binder = SampleData::newBinder(TransactionsReturn(STATUS_OK),
280                                            ExpectLifetimeTransactions(1));
281 
282   EXPECT_OK(SampleData::transact(
283       binder, kCode, WriteNothingToParcel, [&](const AParcel* out) {
284         bool readTarget = false;
285         EXPECT_EQ(STATUS_NOT_ENOUGH_DATA, AParcel_readBool(out, &readTarget));
286         EXPECT_FALSE(readTarget);
287         return STATUS_OK;
288       }));
289   AIBinder_decStrong(binder);
290 }
291 
TEST_F(NdkBinderTest_AParcel,ReturnParcelPosition)292 TEST_F(NdkBinderTest_AParcel, ReturnParcelPosition) {
293   AIBinder* binder = SampleData::newBinder(
294       [&](transaction_code_t, const AParcel* /*in*/, AParcel* out) {
295         size_t position = AParcel_getDataPosition(out);
296         EXPECT_EQ(position, AParcel_getDataPosition(out));
297         EXPECT_OK(AParcel_setDataPosition(out, position));
298         EXPECT_EQ(position, AParcel_getDataPosition(out));
299 
300         return STATUS_OK;
301       },
302       ExpectLifetimeTransactions(1));
303 
304   EXPECT_OK(SampleData::transact(binder, kCode, WriteNothingToParcel,
305                                  ReadNothingFromParcel));
306 
307   AIBinder_decStrong(binder);
308 }
309 
TEST_F(NdkBinderTest_AParcel,TooLargePosition)310 TEST_F(NdkBinderTest_AParcel, TooLargePosition) {
311   AIBinder* binder = SampleData::newBinder(
312       [&](transaction_code_t, const AParcel* /*in*/, AParcel* out) {
313         EXPECT_OK(AParcel_setDataPosition(out, 0));
314         EXPECT_OK(AParcel_setDataPosition(out, INT32_MAX));
315         EXPECT_EQ(STATUS_BAD_VALUE, AParcel_setDataPosition(out, -1));
316         EXPECT_EQ(STATUS_BAD_VALUE, AParcel_setDataPosition(out, -2));
317         return STATUS_OK;
318       },
319       ExpectLifetimeTransactions(1));
320 
321   EXPECT_OK(SampleData::transact(binder, kCode, WriteNothingToParcel,
322                                  ReadNothingFromParcel));
323 
324   AIBinder_decStrong(binder);
325 }
326 
TEST_F(NdkBinderTest_AParcel,RewritePositions)327 TEST_F(NdkBinderTest_AParcel, RewritePositions) {
328   const std::string kTestString1 = "asdf";
329   const std::string kTestString2 = "aoeu";
330 
331   // v-- position     v-- postPosition
332   // | delta | "asdf" | "aoeu" |
333   //         ^-- prePosition
334   //
335   // uint32_t delta = postPosition - prePosition
336 
337   AIBinder* binder = SampleData::newBinder(
338       [&](transaction_code_t, const AParcel* in, AParcel* /*out*/) {
339         uint32_t delta;
340         EXPECT_OK(AParcel_readUint32(in, &delta));
341         size_t prePosition = AParcel_getDataPosition(in);
342         size_t postPosition = prePosition + delta;
343 
344         std::string readString;
345 
346         EXPECT_OK(AParcel_setDataPosition(in, postPosition));
347         EXPECT_OK(::ndk::AParcel_readString(in, &readString));
348         EXPECT_EQ(kTestString2, readString);
349 
350         EXPECT_OK(AParcel_setDataPosition(in, prePosition));
351         EXPECT_OK(::ndk::AParcel_readString(in, &readString));
352         EXPECT_EQ(kTestString1, readString);
353 
354         EXPECT_EQ(postPosition, AParcel_getDataPosition(in));
355 
356         return STATUS_OK;
357       },
358       ExpectLifetimeTransactions(1));
359 
360   EXPECT_OK(SampleData::transact(
361       binder, kCode,
362       [&](AParcel* in) {
363         size_t position = AParcel_getDataPosition(in);
364         EXPECT_OK(AParcel_writeUint32(in, 0));  // placeholder
365         size_t prePosition = AParcel_getDataPosition(in);
366         EXPECT_OK(::ndk::AParcel_writeString(in, kTestString1));
367         size_t postPosition = AParcel_getDataPosition(in);
368         EXPECT_OK(::ndk::AParcel_writeString(in, kTestString2));
369 
370         size_t delta = postPosition - prePosition;
371         EXPECT_OK(AParcel_setDataPosition(in, position));
372         EXPECT_OK(AParcel_writeUint32(in, static_cast<uint32_t>(delta)));
373 
374         return STATUS_OK;
375       },
376       ReadNothingFromParcel));
377 
378   AIBinder_decStrong(binder);
379 }
380 
TEST_F(NdkBinderTest_AParcel,CreateParcelTest)381 TEST_F(NdkBinderTest_AParcel, CreateParcelTest) {
382   AParcel* p = AParcel_create();
383   EXPECT_TRUE(p);
384   EXPECT_EQ(0, AParcel_getDataSize(p));
385   EXPECT_EQ(0, AParcel_getDataPosition(p));
386   AParcel_delete(p);
387 }
388 
TEST_F(NdkBinderTest_AParcel,AppendFromTest)389 TEST_F(NdkBinderTest_AParcel, AppendFromTest) {
390   AParcel* p1 = AParcel_create();
391   AParcel* p2 = AParcel_create();
392 
393   AParcel_writeInt32(p1, 42);
394 
395   AParcel_appendFrom(p1, p2, 0, AParcel_getDataSize(p1));
396   EXPECT_EQ(AParcel_getDataSize(p1), AParcel_getDataSize(p1));
397 
398   int32_t actual = 0;
399   AParcel_setDataPosition(p2, 0);
400   AParcel_readInt32(p2, &actual);
401 
402   EXPECT_EQ(42, actual);
403 
404   AParcel_delete(p1);
405   AParcel_delete(p2);
406 }
407 
TEST_F(NdkBinderTest_AParcel,ResetTest)408 TEST_F(NdkBinderTest_AParcel, ResetTest) {
409   AParcel* p = AParcel_create();
410 
411   AParcel_writeInt32(p, 42);
412   AParcel_reset(p);
413   EXPECT_EQ(0, AParcel_getDataSize(p));
414   EXPECT_EQ(0, AParcel_getDataPosition(p));
415 
416   AParcel_writeInt32(p, 24);
417   AParcel_setDataPosition(p, 0);
418   int actual = 0;
419   AParcel_readInt32(p, &actual);
420 
421   EXPECT_EQ(24, actual);
422   EXPECT_EQ(AParcel_getDataSize(p), AParcel_getDataPosition(p));
423 
424   AParcel_delete(p);
425 }
426 
TEST_F(NdkBinderTest_AParcel,GetDataSizeTest)427 TEST_F(NdkBinderTest_AParcel, GetDataSizeTest) {
428   AParcel* p = AParcel_create();
429 
430   AParcel_writeInt32(p, 42);
431   EXPECT_EQ(AParcel_getDataSize(p), AParcel_getDataPosition(p));
432 
433   AParcel_delete(p);
434 }
435 
TEST_F(NdkBinderTest_AParcel,MarshalUnmarshalTest)436 TEST_F(NdkBinderTest_AParcel, MarshalUnmarshalTest) {
437   AParcel* p1 = AParcel_create();
438   AParcel* p2 = AParcel_create();
439 
440   AParcel_writeInt32(p1, 42);
441   int dataSize = AParcel_getDataSize(p1);
442   uint8_t* data = new uint8_t[dataSize];
443   EXPECT_OK(AParcel_marshal(p1, data, 0, dataSize));
444 
445   EXPECT_OK(AParcel_unmarshal(p2, data, dataSize));
446 
447   int32_t actual = 0;
448   AParcel_setDataPosition(p2, 0);
449   AParcel_readInt32(p2, &actual);
450 
451   EXPECT_EQ(42, actual);
452 
453   AParcel_delete(p1);
454   AParcel_delete(p2);
455   delete[] data;
456 }
457 
TEST_F(NdkBinderTest_AParcel,MarshalParcelWithBinderTest)458 TEST_F(NdkBinderTest_AParcel, MarshalParcelWithBinderTest) {
459   AParcel* p = AParcel_create();
460 
461   AIBinder* binder = SampleData::newBinder();
462   EXPECT_OK(AParcel_writeStrongBinder(p, binder));
463 
464   int dataSize = AParcel_getDataSize(p);
465   uint8_t* data = new uint8_t[dataSize];
466   EXPECT_EQ(STATUS_INVALID_OPERATION, AParcel_marshal(p, data, 0, dataSize));
467 
468   AIBinder_decStrong(binder);
469   AParcel_delete(p);
470   delete[] data;
471 }
472 
TEST_F(NdkBinderTest_AParcel,MarshalParcelWithFdTest)473 TEST_F(NdkBinderTest_AParcel, MarshalParcelWithFdTest) {
474   AParcel* p = AParcel_create();
475 
476   EXPECT_OK(AParcel_writeParcelFileDescriptor(p, 1));
477 
478   int dataSize = AParcel_getDataSize(p);
479   uint8_t* data = new uint8_t[dataSize];
480   EXPECT_EQ(STATUS_INVALID_OPERATION, AParcel_marshal(p, data, 0, dataSize));
481 
482   AParcel_delete(p);
483   delete[] data;
484 }
485 
TEST_F(NdkBinderTest_AParcel,MarshalParcelBufferTooSmall)486 TEST_F(NdkBinderTest_AParcel, MarshalParcelBufferTooSmall) {
487   AParcel* p = AParcel_create();
488 
489   AParcel_writeInt32(p, 42);
490   int dataSize = AParcel_getDataSize(p);
491   uint8_t* data = new uint8_t[dataSize];
492   EXPECT_EQ(STATUS_BAD_VALUE, AParcel_marshal(p, data, 1, dataSize));
493 
494   AParcel_delete(p);
495   delete[] data;
496 }
497