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