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 <hidl/HidlSupport.h>
25 #include <hidl/HidlTransportSupport.h>
26 #include <hidl/LegacySupport.h>
27 #include <hidl/ServiceManagement.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::isHidlSupported;
41 using android::hardware::media::bufferpool::V1_0::IClientManager;
42 using android::hardware::media::bufferpool::V1_0::ResultStatus;
43 using android::hardware::media::bufferpool::V1_0::implementation::BufferId;
44 using android::hardware::media::bufferpool::V1_0::implementation::ClientManager;
45 using android::hardware::media::bufferpool::V1_0::implementation::ConnectionId;
46 using android::hardware::media::bufferpool::V1_0::implementation::TransactionId;
47 using android::hardware::media::bufferpool::BufferPoolData;
48
49 namespace {
50
51 // communication message types between processes.
52 enum PipeCommand : int32_t {
53 INIT_OK = 0,
54 INIT_ERROR,
55 SEND,
56 RECEIVE_OK,
57 RECEIVE_ERROR,
58 };
59
60 // communication message between processes.
61 union PipeMessage {
62 struct {
63 int32_t command;
64 BufferId bufferId;
65 ConnectionId connectionId;
66 TransactionId transactionId;
67 int64_t timestampUs;
68 } data;
69 char array[0];
70 };
71
72 // media.bufferpool test setup
73 class BufferpoolMultiTest : public ::testing::Test {
74 public:
SetUp()75 virtual void SetUp() override {
76 ResultStatus status;
77 mReceiverPid = -1;
78 mConnectionValid = false;
79
80 ASSERT_TRUE(pipe(mCommandPipeFds) == 0);
81 ASSERT_TRUE(pipe(mResultPipeFds) == 0);
82
83 mReceiverPid = fork();
84 ASSERT_TRUE(mReceiverPid >= 0);
85
86 if (mReceiverPid == 0) {
87 doReceiver();
88 // In order to ignore gtest behaviour, wait for being killed from
89 // tearDown
90 pause();
91 }
92
93 mManager = ClientManager::getInstance();
94 ASSERT_NE(mManager, nullptr);
95
96 mAllocator = std::make_shared<TestBufferPoolAllocator>();
97 ASSERT_TRUE((bool)mAllocator);
98
99 status = mManager->create(mAllocator, &mConnectionId);
100 ASSERT_TRUE(status == ResultStatus::OK);
101 mConnectionValid = true;
102 }
103
TearDown()104 virtual void TearDown() override {
105 if (mReceiverPid > 0) {
106 kill(mReceiverPid, SIGKILL);
107 int wstatus;
108 wait(&wstatus);
109 }
110
111 if (mConnectionValid) {
112 mManager->close(mConnectionId);
113 }
114 }
115
116 protected:
description(const std::string & description)117 static void description(const std::string& description) {
118 RecordProperty("description", description);
119 }
120
121 android::sp<ClientManager> mManager;
122 std::shared_ptr<BufferPoolAllocator> mAllocator;
123 bool mConnectionValid;
124 ConnectionId mConnectionId;
125 pid_t mReceiverPid;
126 int mCommandPipeFds[2];
127 int mResultPipeFds[2];
128
sendMessage(int * pipes,const PipeMessage & message)129 bool sendMessage(int *pipes, const PipeMessage &message) {
130 int ret = write(pipes[1], message.array, sizeof(PipeMessage));
131 return ret == sizeof(PipeMessage);
132 }
133
receiveMessage(int * pipes,PipeMessage * message)134 bool receiveMessage(int *pipes, PipeMessage *message) {
135 int ret = read(pipes[0], message->array, sizeof(PipeMessage));
136 return ret == sizeof(PipeMessage);
137 }
138
doReceiver()139 void doReceiver() {
140 configureRpcThreadpool(1, false);
141 PipeMessage message;
142 mManager = ClientManager::getInstance();
143 if (!mManager) {
144 message.data.command = PipeCommand::INIT_ERROR;
145 sendMessage(mResultPipeFds, message);
146 return;
147 }
148 android::status_t status = mManager->registerAsService();
149 if (status != android::OK) {
150 message.data.command = PipeCommand::INIT_ERROR;
151 sendMessage(mResultPipeFds, message);
152 return;
153 }
154 message.data.command = PipeCommand::INIT_OK;
155 sendMessage(mResultPipeFds, message);
156
157 receiveMessage(mCommandPipeFds, &message);
158 {
159 native_handle_t *rhandle = nullptr;
160 std::shared_ptr<BufferPoolData> rbuffer;
161 ResultStatus status = mManager->receive(
162 message.data.connectionId, message.data.transactionId,
163 message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
164 mManager->close(message.data.connectionId);
165 if (status != ResultStatus::OK) {
166 if (!TestBufferPoolAllocator::Verify(rhandle, 0x77)) {
167 message.data.command = PipeCommand::RECEIVE_ERROR;
168 sendMessage(mResultPipeFds, message);
169 return;
170 }
171 }
172 }
173 message.data.command = PipeCommand::RECEIVE_OK;
174 sendMessage(mResultPipeFds, message);
175 }
176 };
177
178 // Buffer transfer test between processes.
TEST_F(BufferpoolMultiTest,TransferBuffer)179 TEST_F(BufferpoolMultiTest, TransferBuffer) {
180 ResultStatus status;
181 PipeMessage message;
182
183 if (!isHidlSupported()) GTEST_SKIP() << "HIDL is not supported on this device";
184 ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
185
186 android::sp<IClientManager> receiver = IClientManager::getService();
187 ConnectionId receiverId;
188 ASSERT_TRUE((bool)receiver);
189
190 status = mManager->registerSender(receiver, mConnectionId, &receiverId);
191 ASSERT_TRUE(status == ResultStatus::OK);
192 {
193 native_handle_t *shandle = nullptr;
194 std::shared_ptr<BufferPoolData> sbuffer;
195 TransactionId transactionId;
196 int64_t postUs;
197 std::vector<uint8_t> vecParams;
198
199 getTestAllocatorParams(&vecParams);
200 status = mManager->allocate(mConnectionId, vecParams, &shandle, &sbuffer);
201 ASSERT_TRUE(status == ResultStatus::OK);
202
203 ASSERT_TRUE(TestBufferPoolAllocator::Fill(shandle, 0x77));
204
205 status = mManager->postSend(receiverId, sbuffer, &transactionId, &postUs);
206 ASSERT_TRUE(status == ResultStatus::OK);
207
208 message.data.command = PipeCommand::SEND;
209 message.data.bufferId = sbuffer->mId;
210 message.data.connectionId = receiverId;
211 message.data.transactionId = transactionId;
212 message.data.timestampUs = postUs;
213 sendMessage(mCommandPipeFds, message);
214 }
215 EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
216 }
217
218 } // anonymous namespace
219
main(int argc,char ** argv)220 int main(int argc, char** argv) {
221 android::hardware::details::setTrebleTestingOverride(true);
222 ::testing::InitGoogleTest(&argc, argv);
223 int status = RUN_ALL_TESTS();
224 LOG(INFO) << "Test result = " << status;
225 return status;
226 }
227