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