Merge "media.bufferpool@1.0 unit tests"
diff --git a/media/libstagefright/codec2/vndk/bufferpool/Android.bp b/media/libstagefright/codec2/vndk/bufferpool/Android.bp
index f0588d5..c7aa07b 100644
--- a/media/libstagefright/codec2/vndk/bufferpool/Android.bp
+++ b/media/libstagefright/codec2/vndk/bufferpool/Android.bp
@@ -1,5 +1,5 @@
-cc_library_shared {
- name: "android.hardware.media.bufferpool@1.0-impl",
+cc_library {
+ name: "libstagefright_bufferpool@1.0",
vendor_available: true,
vndk: {
enabled: true,
diff --git a/media/libstagefright/codec2/vndk/bufferpool/vts/Android.bp b/media/libstagefright/codec2/vndk/bufferpool/vts/Android.bp
new file mode 100644
index 0000000..074d4bc
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/bufferpool/vts/Android.bp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+ name: "VtsVndkHidlBufferpoolV1_0TargetSingleTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "single.cpp",
+ ],
+ static_libs: [
+ "android.hardware.media.bufferpool@1.0",
+ "libion",
+ "libstagefright_bufferpool@1.0",
+ ],
+ shared_libs: [
+ "libfmq",
+ "libstagefright_codec2",
+ "libstagefright_codec2_vndk",
+ ],
+ compile_multilib: "both",
+}
+
+cc_test {
+ name: "VtsVndkHidlBufferpoolV1_0TargetMultiTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "multi.cpp",
+ ],
+ static_libs: [
+ "android.hardware.media.bufferpool@1.0",
+ "libion",
+ "libstagefright_bufferpool@1.0",
+ ],
+ shared_libs: [
+ "libfmq",
+ "libstagefright_codec2",
+ "libstagefright_codec2_vndk",
+ ],
+ compile_multilib: "both",
+}
diff --git a/media/libstagefright/codec2/vndk/bufferpool/vts/OWNERS b/media/libstagefright/codec2/vndk/bufferpool/vts/OWNERS
new file mode 100644
index 0000000..4c3f7a1
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/bufferpool/vts/OWNERS
@@ -0,0 +1,7 @@
+# Media team
+taklee@google.com
+lajos@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/media/libstagefright/codec2/vndk/bufferpool/vts/multi.cpp b/media/libstagefright/codec2/vndk/bufferpool/vts/multi.cpp
new file mode 100644
index 0000000..3ad8b6c
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/bufferpool/vts/multi.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "buffferpool_unit_test"
+
+#include <gtest/gtest.h>
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2PlatformSupport.h>
+#include <ClientManager.h>
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+#include <hidl/Status.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+using android::C2AllocatorIon;
+using android::C2PlatformAllocatorStore;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::hidl_handle;
+using android::hardware::media::bufferpool::V1_0::IAccessor;
+using android::hardware::media::bufferpool::V1_0::IClientManager;
+using android::hardware::media::bufferpool::V1_0::ResultStatus;
+using android::hardware::media::bufferpool::V1_0::implementation::BufferId;
+using android::hardware::media::bufferpool::V1_0::implementation::ClientManager;
+using android::hardware::media::bufferpool::V1_0::implementation::ConnectionId;
+using android::hardware::media::bufferpool::V1_0::implementation::TransactionId;
+
+namespace {
+
+// Buffer allocation size for tests.
+constexpr static int kAllocationSize = 1024 * 10;
+
+// communication message types between processes.
+enum PipeCommand : int32_t {
+ INIT_OK = 0,
+ INIT_ERROR,
+ SEND,
+ RECEIVE_OK,
+ RECEIVE_ERROR,
+};
+
+// communication message between processes.
+union PipeMessage {
+ struct {
+ int32_t command;
+ BufferId bufferId;
+ ConnectionId connectionId;
+ TransactionId transactionId;
+ int64_t timestampUs;
+ } data;
+ char array[0];
+};
+
+// media.bufferpool test setup
+class BufferpoolMultiTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ ResultStatus status;
+ mReceiverPid = -1;
+
+ ASSERT_TRUE(pipe(mCommandPipeFds) == 0);
+ ASSERT_TRUE(pipe(mResultPipeFds) == 0);
+
+ mReceiverPid = fork();
+ ASSERT_TRUE(mReceiverPid >= 0);
+
+ if (mReceiverPid == 0) {
+ doReceiver();
+ return;
+ }
+
+ mManager = ClientManager::getInstance();
+ ASSERT_NE(mManager, nullptr);
+
+ mAllocator =
+ std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
+ ASSERT_TRUE((bool)mAllocator);
+
+ status = mManager->create(mAllocator, true, &mConnectionId);
+ ASSERT_TRUE(status == ResultStatus::OK);
+
+ status = mManager->getAccessor(mConnectionId, &mAccessor);
+ ASSERT_TRUE(status == ResultStatus::OK && (bool)mAccessor);
+ }
+
+ virtual void TearDown() override {
+ if (mReceiverPid > 0) {
+ kill(mReceiverPid, SIGKILL);
+ int wstatus;
+ wait(&wstatus);
+ }
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ android::sp<ClientManager> mManager;
+ android::sp<IAccessor> mAccessor;
+ std::shared_ptr<C2Allocator> mAllocator;
+ ConnectionId mConnectionId;
+ pid_t mReceiverPid;
+ int mCommandPipeFds[2];
+ int mResultPipeFds[2];
+
+ void getAllocationParams(std::vector<uint8_t>* vecParams) {
+ union Params {
+ struct {
+ uint32_t capacity;
+ C2MemoryUsage usage;
+ } data;
+ uint8_t array[0];
+ Params()
+ : data{kAllocationSize,
+ {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}} {}
+ } params;
+ vecParams->assign(params.array, params.array + sizeof(params));
+ }
+
+ bool sendMessage(int *pipes, const PipeMessage &message) {
+ int ret = write(pipes[1], message.array, sizeof(PipeMessage));
+ return ret == sizeof(PipeMessage);
+ }
+
+ bool receiveMessage(int *pipes, PipeMessage *message) {
+ int ret = read(pipes[0], message->array, sizeof(PipeMessage));
+ return ret == sizeof(PipeMessage);
+ }
+
+ void doReceiver() {
+ configureRpcThreadpool(1, false);
+ PipeMessage message;
+ mManager = ClientManager::getInstance();
+ if (!mManager) {
+ message.data.command = PipeCommand::INIT_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ android::status_t status = mManager->registerAsService();
+ if (status != android::OK) {
+ message.data.command = PipeCommand::INIT_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ message.data.command = PipeCommand::INIT_OK;
+ sendMessage(mResultPipeFds, message);
+
+ receiveMessage(mCommandPipeFds, &message);
+ {
+ std::shared_ptr<_C2BlockPoolData> rbuffer;
+ ResultStatus status = mManager->receive(
+ message.data.connectionId, message.data.transactionId,
+ message.data.bufferId, message.data.timestampUs, &rbuffer);
+ if (status != ResultStatus::OK) {
+ message.data.command = PipeCommand::RECEIVE_ERROR;
+ sendMessage(mResultPipeFds, message);
+ return;
+ }
+ }
+ message.data.command = PipeCommand::RECEIVE_OK;
+ sendMessage(mResultPipeFds, message);
+ while(1); // An easy way to ignore gtest behaviour.
+ }
+};
+
+// Buffer transfer test between processes.
+TEST_F(BufferpoolMultiTest, TransferBuffer) {
+ ResultStatus status;
+ PipeMessage message;
+
+ ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
+
+ android::sp<IClientManager> receiver = IClientManager::getService();
+ ConnectionId receiverId;
+ ASSERT_TRUE((bool)receiver);
+
+ receiver->registerSender(
+ mAccessor, [&status, &receiverId]
+ (ResultStatus outStatus, ConnectionId outId) {
+ status = outStatus;
+ receiverId = outId;
+ });
+ ASSERT_TRUE(status == ResultStatus::OK);
+ {
+ std::shared_ptr<_C2BlockPoolData> sbuffer;
+ TransactionId transactionId;
+ int64_t postUs;
+ std::vector<uint8_t> vecParams;
+
+ getAllocationParams(&vecParams);
+ status = mManager->allocate(mConnectionId, vecParams, &sbuffer);
+ ASSERT_TRUE(status == ResultStatus::OK);
+
+ status = mManager->postSend(mConnectionId, receiverId, sbuffer,
+ &transactionId, &postUs);
+ ASSERT_TRUE(status == ResultStatus::OK);
+
+ message.data.command = PipeCommand::SEND;
+ message.data.bufferId = sbuffer->mId;
+ message.data.connectionId = receiverId;
+ message.data.transactionId = transactionId;
+ message.data.timestampUs = postUs;
+ sendMessage(mCommandPipeFds, message);
+ }
+ EXPECT_TRUE(receiveMessage(mResultPipeFds, &message));
+}
+
+} // anonymous namespace
+
+int main(int argc, char** argv) {
+ setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
diff --git a/media/libstagefright/codec2/vndk/bufferpool/vts/single.cpp b/media/libstagefright/codec2/vndk/bufferpool/vts/single.cpp
new file mode 100644
index 0000000..89eb631
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/bufferpool/vts/single.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "buffferpool_unit_test"
+
+#include <gtest/gtest.h>
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2PlatformSupport.h>
+#include <ClientManager.h>
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+#include <hidl/Status.h>
+#include <unistd.h>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+using android::C2AllocatorIon;
+using android::C2PlatformAllocatorStore;
+using android::hardware::hidl_handle;
+using android::hardware::media::bufferpool::V1_0::IAccessor;
+using android::hardware::media::bufferpool::V1_0::ResultStatus;
+using android::hardware::media::bufferpool::V1_0::implementation::BufferId;
+using android::hardware::media::bufferpool::V1_0::implementation::ClientManager;
+using android::hardware::media::bufferpool::V1_0::implementation::ConnectionId;
+using android::hardware::media::bufferpool::V1_0::implementation::TransactionId;
+
+namespace {
+
+// Buffer allocation size for tests.
+constexpr static int kAllocationSize = 1024 * 10;
+
+// Number of iteration for buffer allocation test.
+constexpr static int kNumAllocationTest = 3;
+
+// Number of iteration for buffer recycling test.
+constexpr static int kNumRecycleTest = 3;
+
+// media.bufferpool test setup
+class BufferpoolSingleTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ ResultStatus status;
+
+ mManager = ClientManager::getInstance();
+ ASSERT_NE(mManager, nullptr);
+
+ mAllocator =
+ std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
+ ASSERT_TRUE((bool)mAllocator);
+
+ status = mManager->create(mAllocator, true, &mConnectionId);
+ ASSERT_TRUE(status == ResultStatus::OK);
+
+ status = mManager->getAccessor(mConnectionId, &mAccessor);
+ ASSERT_TRUE(status == ResultStatus::OK && (bool)mAccessor);
+
+ ConnectionId& receiverId = mReceiverId;
+ mManager->registerSender(
+ mAccessor,
+ [&status, &receiverId](ResultStatus hidlStatus, ConnectionId hidlId) {
+ status = hidlStatus;
+ receiverId = hidlId;
+ });
+ ASSERT_TRUE(status == ResultStatus::ALREADY_EXISTS &&
+ receiverId == mConnectionId);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ android::sp<ClientManager> mManager;
+ android::sp<IAccessor> mAccessor;
+ std::shared_ptr<C2Allocator> mAllocator;
+ ConnectionId mConnectionId;
+ ConnectionId mReceiverId;
+
+ void getAllocationParams(std::vector<uint8_t>* vecParams) {
+ union Params {
+ struct {
+ uint32_t capacity;
+ C2MemoryUsage usage;
+ } data;
+ uint8_t array[0];
+ Params()
+ : data{kAllocationSize,
+ {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}} {}
+ } params;
+ vecParams->assign(params.array, params.array + sizeof(params));
+ }
+};
+
+// Buffer allocation test.
+// Check whether each buffer allocation is done successfully with
+// unique buffer id.
+TEST_F(BufferpoolSingleTest, AllocateBuffer) {
+ ResultStatus status;
+ std::vector<uint8_t> vecParams;
+ getAllocationParams(&vecParams);
+
+ std::shared_ptr<_C2BlockPoolData> buffer[kNumAllocationTest];
+ for (int i = 0; i < kNumAllocationTest; ++i) {
+ status = mManager->allocate(mConnectionId, vecParams, &buffer[i]);
+ ASSERT_TRUE(status == ResultStatus::OK);
+ }
+ for (int i = 0; i < kNumAllocationTest; ++i) {
+ for (int j = i + 1; j < kNumAllocationTest; ++j) {
+ ASSERT_TRUE(buffer[i]->mId != buffer[j]->mId);
+ }
+ }
+ EXPECT_TRUE(kNumAllocationTest > 1);
+}
+
+// Buffer recycle test.
+// Check whether de-allocated buffers are recycled.
+TEST_F(BufferpoolSingleTest, RecycleBuffer) {
+ ResultStatus status;
+ std::vector<uint8_t> vecParams;
+ getAllocationParams(&vecParams);
+
+ BufferId bid[kNumRecycleTest];
+ for (int i = 0; i < kNumRecycleTest; ++i) {
+ std::shared_ptr<_C2BlockPoolData> buffer;
+ status = mManager->allocate(mConnectionId, vecParams, &buffer);
+ ASSERT_TRUE(status == ResultStatus::OK);
+ bid[i] = buffer->mId;
+ }
+ for (int i = 1; i < kNumRecycleTest; ++i) {
+ ASSERT_TRUE(bid[i - 1] == bid[i]);
+ }
+ EXPECT_TRUE(kNumRecycleTest > 1);
+}
+
+// Buffer transfer test.
+// Check whether buffer is transferred to another client successfully.
+TEST_F(BufferpoolSingleTest, TransferBuffer) {
+ ResultStatus status;
+ std::vector<uint8_t> vecParams;
+ getAllocationParams(&vecParams);
+ std::shared_ptr<_C2BlockPoolData> sbuffer, rbuffer;
+
+ TransactionId transactionId;
+ int64_t postUs;
+
+ status = mManager->allocate(mConnectionId, vecParams, &sbuffer);
+ ASSERT_TRUE(status == ResultStatus::OK);
+ status = mManager->postSend(mConnectionId, mReceiverId, sbuffer,
+ &transactionId, &postUs);
+ ASSERT_TRUE(status == ResultStatus::OK);
+ status = mManager->receive(mReceiverId, transactionId, sbuffer->mId, postUs,
+ &rbuffer);
+ EXPECT_TRUE(status == ResultStatus::OK);
+}
+
+} // anonymous namespace
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}