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