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
17 #define LOG_TAG "buffferpool_unit_test"
18
19 #include <gtest/gtest.h>
20
21 #include <android-base/logging.h>
22 #include <binder/ProcessState.h>
23 #include <bufferpool/ClientManager.h>
24 #include <errno.h>
25 #include <hidl/HidlSupport.h>
26 #include <hidl/HidlTransportSupport.h>
27 #include <hidl/LegacySupport.h>
28 #include <hidl/Status.h>
29 #include <signal.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33 #include <iostream>
34 #include <memory>
35 #include <vector>
36 #include "allocator.h"
37
38 using android::hardware::configureRpcThreadpool;
39 using android::hardware::hidl_handle;
40 using android::hardware::media::bufferpool::V2_0::IClientManager;
41 using android::hardware::media::bufferpool::V2_0::ResultStatus;
42 using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
43 using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
44 using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
45 using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
46 using android::hardware::media::bufferpool::BufferPoolData;
47
48 namespace {
49
50 // communication message types between processes.
51 enum PipeCommand : int32_t {
52 INIT_OK = 0,
53 INIT_ERROR,
54 SEND,
55 RECEIVE_OK,
56 RECEIVE_ERROR,
57 };
58
59 // communication message between processes.
60 union PipeMessage {
61 struct {
62 int32_t command;
63 BufferId bufferId;
64 ConnectionId connectionId;
65 TransactionId transactionId;
66 int64_t timestampUs;
67 } data;
68 char array[0];
69 };
70
71 constexpr int kSignalInt = 200;
72
73 // media.bufferpool test setup
74 class BufferpoolMultiTest : public ::testing::Test {
75 public:
SetUp()76 virtual void SetUp() override {
77 ResultStatus status;
78 mReceiverPid = -1;
79 mConnectionValid = false;
80
81 ASSERT_TRUE(pipe(mCommandPipeFds) == 0);
82 ASSERT_TRUE(pipe(mResultPipeFds) == 0);
83
84 mReceiverPid = fork();
85 ASSERT_TRUE(mReceiverPid >= 0);
86
87 if (mReceiverPid == 0) {
88 doReceiver();
89 // In order to ignore gtest behaviour, wait for being killed from
90 // tearDown
91 pause();
92 }
93
94 mManager = ClientManager::getInstance();
95 ASSERT_NE(mManager, nullptr);
96
97 mAllocator = std::make_shared<TestBufferPoolAllocator>();
98 ASSERT_TRUE((bool)mAllocator);
99
100 status = mManager->create(mAllocator, &mConnectionId);
101 ASSERT_TRUE(status == ResultStatus::OK);
102 mConnectionValid = true;
103 }
104
TearDown()105 virtual void TearDown() override {
106 if (mReceiverPid > 0) {
107 kill(mReceiverPid, SIGKILL);
108 int wstatus;
109 wait(&wstatus);
110 }
111
112 if (mConnectionValid) {
113 mManager->close(mConnectionId);
114 }
115 }
116
117 protected:
description(const std::string & description)118 static void description(const std::string& description) {
119 RecordProperty("description", description);
120 }
121
122 android::sp<ClientManager> mManager;
123 std::shared_ptr<BufferPoolAllocator> mAllocator;
124 bool mConnectionValid;
125 ConnectionId mConnectionId;
126 pid_t mReceiverPid;
127 int mCommandPipeFds[2];
128 int mResultPipeFds[2];
129
sendMessage(int * pipes,const PipeMessage & message)130 bool sendMessage(int *pipes, const PipeMessage &message) {
131 int ret = write(pipes[1], message.array, sizeof(PipeMessage));
132 return ret == sizeof(PipeMessage);
133 }
134
receiveMessage(int * pipes,PipeMessage * message)135 bool receiveMessage(int *pipes, PipeMessage *message) {
136 int ret = read(pipes[0], message->array, sizeof(PipeMessage));
137 return ret == sizeof(PipeMessage);
138 }
139
doReceiver()140 void doReceiver() {
141 configureRpcThreadpool(1, false);
142 PipeMessage message;
143 mManager = ClientManager::getInstance();
144 if (!mManager) {
145 message.data.command = PipeCommand::INIT_ERROR;
146 sendMessage(mResultPipeFds, message);
147 return;
148 }
149 android::status_t status = mManager->registerAsService();
150 if (status != android::OK) {
151 message.data.command = PipeCommand::INIT_ERROR;
152 sendMessage(mResultPipeFds, message);
153 return;
154 }
155 message.data.command = PipeCommand::INIT_OK;
156 sendMessage(mResultPipeFds, message);
157
158 int val = 0;
159 receiveMessage(mCommandPipeFds, &message);
160 {
161 native_handle_t *rhandle = nullptr;
162 std::shared_ptr<BufferPoolData> rbuffer;
163 void *mem = nullptr;
164 IpcMutex *mutex = nullptr;
165 ResultStatus status = mManager->receive(
166 message.data.connectionId, message.data.transactionId,
167 message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
168 mManager->close(message.data.connectionId);
169 if (status != ResultStatus::OK) {
170 message.data.command = PipeCommand::RECEIVE_ERROR;
171 sendMessage(mResultPipeFds, message);
172 return;
173 }
174 if (!TestBufferPoolAllocator::MapMemoryForMutex(rhandle, &mem)) {
175 message.data.command = PipeCommand::RECEIVE_ERROR;
176 sendMessage(mResultPipeFds, message);
177 return;
178 }
179 mutex = IpcMutex::Import(mem);
180 pthread_mutex_lock(&(mutex->lock));
181 while (mutex->signalled != true) {
182 pthread_cond_wait(&(mutex->cond), &(mutex->lock));
183 }
184 val = mutex->counter;
185 pthread_mutex_unlock(&(mutex->lock));
186
187 (void)TestBufferPoolAllocator::UnmapMemoryForMutex(mem);
188 if (rhandle) {
189 native_handle_close(rhandle);
190 native_handle_delete(rhandle);
191 }
192 }
193 if (val == kSignalInt) {
194 message.data.command = PipeCommand::RECEIVE_OK;
195 } else {
196 message.data.command = PipeCommand::RECEIVE_ERROR;
197 }
198 sendMessage(mResultPipeFds, message);
199 }
200 };
201
202 // Buffer transfer test between processes.
TEST_F(BufferpoolMultiTest,TransferBuffer)203 TEST_F(BufferpoolMultiTest, TransferBuffer) {
204 ResultStatus status;
205 PipeMessage message;
206
207 ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
208
209 android::sp<IClientManager> receiver = IClientManager::getService();
210 ConnectionId receiverId;
211 ASSERT_TRUE((bool)receiver);
212
213 status = mManager->registerSender(receiver, mConnectionId, &receiverId);
214 ASSERT_TRUE(status == ResultStatus::OK);
215 {
216 native_handle_t *shandle = nullptr;
217 std::shared_ptr<BufferPoolData> sbuffer;
218 TransactionId transactionId;
219 int64_t postUs;
220 std::vector<uint8_t> vecParams;
221 void *mem = nullptr;
222 IpcMutex *mutex = nullptr;
223
224 getIpcMutexParams(&vecParams);
225 status = mManager->allocate(mConnectionId, vecParams, &shandle, &sbuffer);
226 ASSERT_TRUE(status == ResultStatus::OK);
227
228 ASSERT_TRUE(TestBufferPoolAllocator::MapMemoryForMutex(shandle, &mem));
229
230 mutex = new(mem) IpcMutex();
231 mutex->init();
232
233 status = mManager->postSend(receiverId, sbuffer, &transactionId, &postUs);
234 ASSERT_TRUE(status == ResultStatus::OK);
235
236 message.data.command = PipeCommand::SEND;
237 message.data.bufferId = sbuffer->mId;
238 message.data.connectionId = receiverId;
239 message.data.transactionId = transactionId;
240 message.data.timestampUs = postUs;
241 sendMessage(mCommandPipeFds, message);
242 for (int i=0; i < 200000000; ++i) {
243 // no-op in order to ensure
244 // pthread_cond_wait is called before pthread_cond_signal
245 }
246 pthread_mutex_lock(&(mutex->lock));
247 mutex->counter = kSignalInt;
248 mutex->signalled = true;
249 pthread_cond_signal(&(mutex->cond));
250 pthread_mutex_unlock(&(mutex->lock));
251 (void)TestBufferPoolAllocator::UnmapMemoryForMutex(mem);
252 if (shandle) {
253 native_handle_close(shandle);
254 native_handle_delete(shandle);
255 }
256 }
257 EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
258 EXPECT_TRUE(message.data.command == PipeCommand::RECEIVE_OK);
259 }
260
261 } // anonymous namespace
262
main(int argc,char ** argv)263 int main(int argc, char** argv) {
264 android::hardware::details::setTrebleTestingOverride(true);
265 ::testing::InitGoogleTest(&argc, argv);
266 int status = RUN_ALL_TESTS();
267 LOG(INFO) << "Test result = " << status;
268 return status;
269 }
270