xref: /aosp_15_r20/frameworks/native/libs/binder/tests/binderRecordedTransactionTest.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2022 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 <binder/RecordedTransaction.h>
18 #include <gtest/gtest.h>
19 #include <utils/Errors.h>
20 
21 using android::Parcel;
22 using android::status_t;
23 using android::binder::unique_fd;
24 using android::binder::debug::RecordedTransaction;
25 
TEST(BinderRecordedTransaction,RoundTripEncoding)26 TEST(BinderRecordedTransaction, RoundTripEncoding) {
27     android::String16 interfaceName("SampleInterface");
28     Parcel d;
29     d.writeInt32(12);
30     d.writeInt64(2);
31     Parcel r;
32     r.writeInt32(99);
33     timespec ts = {1232456, 567890};
34 
35     auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
36     EXPECT_TRUE(transaction.has_value());
37 
38     auto file = std::tmpfile();
39     auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
40 
41     status_t status = transaction->dumpToFile(fd);
42     ASSERT_EQ(android::NO_ERROR, status);
43 
44     std::rewind(file);
45 
46     auto retrievedTransaction = RecordedTransaction::fromFile(fd);
47 
48     EXPECT_EQ(retrievedTransaction->getInterfaceName(), android::String8(interfaceName).c_str());
49     EXPECT_EQ(retrievedTransaction->getCode(), 1);
50     EXPECT_EQ(retrievedTransaction->getFlags(), 42);
51     EXPECT_EQ(retrievedTransaction->getTimestamp().tv_sec, ts.tv_sec);
52     EXPECT_EQ(retrievedTransaction->getTimestamp().tv_nsec, ts.tv_nsec);
53     EXPECT_EQ(retrievedTransaction->getDataParcel().dataSize(), 12);
54     EXPECT_EQ(retrievedTransaction->getReplyParcel().dataSize(), 4);
55     EXPECT_EQ(retrievedTransaction->getReturnedStatus(), 0);
56     EXPECT_EQ(retrievedTransaction->getVersion(), 0);
57 
58     EXPECT_EQ(retrievedTransaction->getDataParcel().readInt32(), 12);
59     EXPECT_EQ(retrievedTransaction->getDataParcel().readInt64(), 2);
60     EXPECT_EQ(retrievedTransaction->getReplyParcel().readInt32(), 99);
61 }
62 
TEST(BinderRecordedTransaction,Checksum)63 TEST(BinderRecordedTransaction, Checksum) {
64     android::String16 interfaceName("SampleInterface");
65     Parcel d;
66     d.writeInt32(12);
67     d.writeInt64(2);
68     Parcel r;
69     r.writeInt32(99);
70     timespec ts = {1232456, 567890};
71     auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
72 
73     auto file = std::tmpfile();
74     auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
75 
76     status_t status = transaction->dumpToFile(fd);
77     ASSERT_EQ(android::NO_ERROR, status);
78 
79     lseek(fd.get(), 9, SEEK_SET);
80     uint32_t badData = 0xffffffff;
81     write(fd.get(), &badData, sizeof(uint32_t));
82     std::rewind(file);
83 
84     auto retrievedTransaction = RecordedTransaction::fromFile(fd);
85 
86     EXPECT_FALSE(retrievedTransaction.has_value());
87 }
88 
TEST(BinderRecordedTransaction,PayloadsExceedPageBoundaries)89 TEST(BinderRecordedTransaction, PayloadsExceedPageBoundaries) {
90     // File contents are read with mmap.
91     // This test verifies that transactions are read from portions
92     // of files that cross page boundaries and don't start at a
93     // page boundary offset of the fd.
94     const size_t pageSize = sysconf(_SC_PAGE_SIZE);
95     const size_t largeDataSize = pageSize + 100;
96     std::vector<uint8_t> largePayload;
97     uint8_t filler = 0xaa;
98     largePayload.insert(largePayload.end(), largeDataSize, filler);
99     android::String16 interfaceName("SampleInterface");
100     Parcel d;
101     d.writeInt32(12);
102     d.writeInt64(2);
103     d.writeByteVector(largePayload);
104     Parcel r;
105     r.writeInt32(99);
106     timespec ts = {1232456, 567890};
107     auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
108 
109     auto file = std::tmpfile();
110     auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
111 
112     // Write to file twice
113     status_t status = transaction->dumpToFile(fd);
114     ASSERT_EQ(android::NO_ERROR, status);
115     status = transaction->dumpToFile(fd);
116     ASSERT_EQ(android::NO_ERROR, status);
117 
118     std::rewind(file);
119 
120     for (int i = 0; i < 2; i++) {
121         auto retrievedTransaction = RecordedTransaction::fromFile(fd);
122 
123         EXPECT_EQ(retrievedTransaction->getCode(), 1);
124         EXPECT_EQ(retrievedTransaction->getFlags(), 42);
125         EXPECT_EQ(retrievedTransaction->getTimestamp().tv_sec, ts.tv_sec);
126         EXPECT_EQ(retrievedTransaction->getTimestamp().tv_nsec, ts.tv_nsec);
127         EXPECT_EQ(retrievedTransaction->getDataParcel().dataSize(), d.dataSize());
128         EXPECT_EQ(retrievedTransaction->getReplyParcel().dataSize(), 4);
129         EXPECT_EQ(retrievedTransaction->getReturnedStatus(), 0);
130         EXPECT_EQ(retrievedTransaction->getVersion(), 0);
131 
132         EXPECT_EQ(retrievedTransaction->getDataParcel().readInt32(), 12);
133         EXPECT_EQ(retrievedTransaction->getDataParcel().readInt64(), 2);
134         std::optional<std::vector<uint8_t>> payloadOut;
135         EXPECT_EQ(retrievedTransaction->getDataParcel().readByteVector(&payloadOut), android::OK);
136         EXPECT_EQ(payloadOut.value(), largePayload);
137 
138         EXPECT_EQ(retrievedTransaction->getReplyParcel().readInt32(), 99);
139     }
140 }
141