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