Add DaydreamVR native libraries and services
Upstreaming the main VR system components from master-dreamos-dev
into goog/master.
Bug: None
Test: `m -j32` succeeds. Sailfish boots and basic_vr sample app works
Change-Id: I853015872afc443aecee10411ef2d6b79184d051
diff --git a/libs/vr/libbufferhub/tests/Android.mk b/libs/vr/libbufferhub/tests/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/libs/vr/libbufferhub/tests/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/libs/vr/libbufferhub/tests/ion_buffer/Android.mk b/libs/vr/libbufferhub/tests/ion_buffer/Android.mk
new file mode 100644
index 0000000..3bfdb7b
--- /dev/null
+++ b/libs/vr/libbufferhub/tests/ion_buffer/Android.mk
@@ -0,0 +1,74 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+COMPONENT_TOP := ${LOCAL_PATH}/../..
+
+LOCAL_SRC_FILES := \
+ ion_buffer-test.cpp \
+ ../../ion_buffer.cpp \
+ ../../mocks/gralloc/gralloc.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libc \
+ libcutils \
+ libutils \
+ liblog
+
+LOCAL_STATIC_LIBRARIES := \
+ libgmock
+
+LOCAL_C_INCLUDES := \
+ ${COMPONENT_TOP}/mocks/gralloc \
+ ${COMPONENT_TOP}/include \
+ $(TOP)/system/core/base/include
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
+
+LOCAL_NATIVE_COVERAGE := true
+
+LOCAL_CFLAGS := -DTRACE=0 -g
+
+LOCAL_MODULE := ion_buffer-test
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ion_buffer-test.cpp \
+ ../../ion_buffer.cpp \
+ ../../mocks/gralloc/gralloc.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog
+
+LOCAL_STATIC_LIBRARIES := \
+ libgmock_host
+
+LOCAL_C_INCLUDES := \
+ ${COMPONENT_TOP}/mocks/gralloc \
+ ${COMPONENT_TOP}/include \
+ $(TOP)/system/core/base/include
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
+
+LOCAL_NATIVE_COVERAGE := true
+
+LOCAL_CFLAGS := -DTRACE=0
+
+LOCAL_MODULE := ion_buffer-host_test
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_HOST_NATIVE_TEST)
+
+.PHONY: dvr_host_native_unit_tests
+dvr_host_native_unit_tests: ion_buffer-host_test
+ifeq (true,$(NATIVE_COVERAGE))
+ ion_buffer-host_test: llvm-cov
+ ion_buffer-test: llvm-cov
+ # This shouldn't be necessary, but the default build with
+ # NATIVE_COVERAGE=true manages to ion_buffer-test without
+ # building llvm-cov (droid is the default target).
+ droid: llvm-cov
+endif
diff --git a/libs/vr/libbufferhub/tests/ion_buffer/ion_buffer-test.cpp b/libs/vr/libbufferhub/tests/ion_buffer/ion_buffer-test.cpp
new file mode 100644
index 0000000..68f82d7
--- /dev/null
+++ b/libs/vr/libbufferhub/tests/ion_buffer/ion_buffer-test.cpp
@@ -0,0 +1,375 @@
+#include <gmock/gmock.h>
+#include <gralloc_mock.h>
+#include <gtest/gtest.h>
+#include <private/dvr/ion_buffer.h>
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+using android::dvr::IonBuffer;
+
+GrallocMock* GrallocMock::staticObject = nullptr;
+
+namespace {
+
+const int w1 = 100;
+const int h1 = 200;
+const int d1 = 2;
+const int f1 = 1;
+const int u1 = 3;
+const int stride1 = 8;
+const int layer_stride1 = 8;
+native_handle_t handle1;
+const int w2 = 150;
+const int h2 = 300;
+const int d2 = 4;
+const int f2 = 2;
+const int u2 = 5;
+const int stride2 = 4;
+const int layer_stride2 = 4;
+native_handle_t handle2;
+const int kMaxFd = 10;
+const int kMaxInt = 10;
+char handleData[sizeof(native_handle_t) + (kMaxFd + kMaxInt) * sizeof(int)];
+native_handle_t* const dataHandle =
+ reinterpret_cast<native_handle_t*>(handleData);
+char refData[sizeof(native_handle_t) + (kMaxFd + kMaxInt) * sizeof(int)];
+native_handle_t* const refHandle = reinterpret_cast<native_handle_t*>(refData);
+
+class IonBufferUnitTest : public ::testing::Test {
+ protected:
+ // You can remove any or all of the following functions if its body
+ // is empty.
+
+ IonBufferUnitTest() {
+ GrallocMock::staticObject = new GrallocMock;
+ // You can do set-up work for each test here.
+ // most ServicefsClients will use this initializer. Use as the
+ // default.
+ }
+
+ virtual ~IonBufferUnitTest() {
+ delete GrallocMock::staticObject;
+ GrallocMock::staticObject = nullptr;
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ void SetUp() override {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ void TearDown() override {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+};
+
+void TestIonBufferState(const IonBuffer& buffer, int w, int h, int d, int f,
+ int u, native_handle_t* handle, int stride,
+ int layer_stride) {
+ EXPECT_EQ(buffer.width(), w);
+ EXPECT_EQ(buffer.height(), h);
+ EXPECT_EQ(buffer.layer_count(), d);
+ EXPECT_EQ(buffer.format(), f);
+ EXPECT_EQ(buffer.usage(), u);
+ EXPECT_EQ(buffer.handle(), handle);
+ EXPECT_EQ(buffer.stride(), stride);
+ EXPECT_EQ(buffer.layer_stride(), layer_stride);
+}
+
+TEST_F(IonBufferUnitTest, TestFreeOnDestruction) {
+ // Set up |alloc|(|w1...|) to succeed once and fail on others calls.
+ EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgPointee<4>(&handle1), SetArgPointee<5>(stride1),
+ Return(0)));
+ // Set up |free| to be called once.
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+
+ IonBuffer buffer;
+ // First call to |alloc| with |w1...| set up to succeed.
+ int ret = buffer.Alloc(w1, h1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
+
+ // Scoped destructor will be called, calling |free| on |handle1|.
+}
+
+TEST_F(IonBufferUnitTest, TestAlloc) {
+ IonBuffer buffer;
+ // Set up |alloc|(|w1...|) to succeed once and fail on others calls.
+ EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
+ .Times(2)
+ .WillOnce(DoAll(SetArgPointee<4>(&handle1), SetArgPointee<5>(stride1),
+ Return(0)))
+ .WillRepeatedly(Return(-1));
+
+ // Set up |alloc|(|w2...|) to succeed once and fail on others calls.
+ EXPECT_CALL(*GrallocMock::staticObject, alloc(w2, h2, f2, u2, _, _))
+ .Times(2)
+ .WillOnce(DoAll(SetArgPointee<4>(&handle2), SetArgPointee<5>(stride2),
+ Return(0)))
+ .WillRepeatedly(Return(-1));
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle2))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+
+ // First call to |alloc| with |w1...| set up to succeed.
+ int ret = buffer.Alloc(w1, h1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
+
+ // First call to |alloc| with |w2...| set up to succeed, |free| should be
+ // called once on |handle1|.
+ ret = buffer.Alloc(w2, h2, f2, u2);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
+
+ // Second call to |alloc| with |w1| is set up to fail.
+ ret = buffer.Alloc(w1, h1, f1, u1);
+ EXPECT_LT(ret, 0);
+ TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
+
+ // |free| on |handle2| should be called here.
+ buffer.FreeHandle();
+ TestIonBufferState(buffer, 0, 0, 0, 0, 0, nullptr, 0, 0);
+
+ // |alloc| is set up to fail.
+ ret = buffer.Alloc(w2, h2, f2, u2);
+ EXPECT_LT(ret, 0);
+ TestIonBufferState(buffer, 0, 0, 0, 0, 0, nullptr, 0, 0);
+}
+
+TEST_F(IonBufferUnitTest, TestReset) {
+ IonBuffer buffer;
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle2))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+ buffer.Reset(&handle1, w1, h1, stride1, f1, u1);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
+ buffer.Reset(&handle2, w2, h2, stride2, f2, u2);
+ TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
+ buffer.FreeHandle();
+}
+
+TEST_F(IonBufferUnitTest, TestImport1) {
+ IonBuffer buffer;
+ EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(&handle1))
+ .Times(3)
+ .WillOnce(Return(0))
+ .WillRepeatedly(Return(-1));
+ EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(&handle2))
+ .Times(3)
+ .WillOnce(Return(0))
+ .WillOnce(Return(-1))
+ .WillOnce(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(&handle1))
+ .Times(1)
+ .WillOnce(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(&handle1))
+ .Times(1);
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(&handle1))
+ .Times(1);
+ EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
+ .Times(1)
+ .WillRepeatedly(DoAll(SetArgPointee<4>(&handle1),
+ SetArgPointee<5>(stride1), Return(0)));
+ EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(&handle2))
+ .Times(2)
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(&handle2))
+ .Times(2);
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(&handle2))
+ .Times(2);
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+
+ int ret = buffer.Import(&handle1, w1, h1, stride1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
+ ret = buffer.Import(&handle2, w2, h2, stride2, f2, u2);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
+ ret = buffer.Alloc(w1, h1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ ret = buffer.Import(&handle2, w2, h2, stride2, f2, u2);
+ EXPECT_LT(ret, 0);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, &handle1, stride1, 0);
+ ret = buffer.Import(&handle2, w2, h2, stride2, f2, u2);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
+ ret = buffer.Import(&handle1, w1, h1, stride1, f1, u1);
+ EXPECT_LT(ret, 0);
+ TestIonBufferState(buffer, w2, h2, 1, f2, u2, &handle2, stride2, 0);
+ buffer.FreeHandle();
+ ret = buffer.Import(&handle1, w1, h1, stride1, f1, u1);
+ EXPECT_LT(ret, 0);
+ TestIonBufferState(buffer, 0, 0, 0, 0, 0, nullptr, 0, 0);
+}
+
+native_handle_t* native_handle_create_impl(int nFds, int nInts) {
+ if ((nFds + nInts) > (kMaxFd + kMaxInt))
+ return nullptr;
+ dataHandle->version = sizeof(native_handle_t);
+ dataHandle->numFds = nFds;
+ dataHandle->numInts = nInts;
+ for (int i = 0; i < nFds + nInts; i++)
+ dataHandle->data[i] = 0;
+ return dataHandle;
+}
+
+TEST_F(IonBufferUnitTest, TestImport2) {
+ IonBuffer buffer;
+ int ints[] = {211, 313, 444};
+ int fds[] = {-1, -1};
+ int ni = sizeof(ints) / sizeof(ints[0]);
+ int nfd = sizeof(fds) / sizeof(fds[0]);
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_create(nfd, ni))
+ .Times(3)
+ .WillOnce(Return(nullptr))
+ .WillRepeatedly(Invoke(native_handle_create_impl));
+ EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(dataHandle))
+ .Times(2)
+ .WillOnce(Return(-1))
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(dataHandle))
+ .Times(2);
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(dataHandle))
+ .Times(2);
+ EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(dataHandle))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+
+ int ret = buffer.Import(fds, -1, ints, ni, w1, h1, stride1, f1, u1);
+ EXPECT_LT(ret, 0);
+ ret = buffer.Import(fds, nfd, ints, -1, w1, h1, stride1, f1, u1);
+ EXPECT_LT(ret, 0);
+ ret = buffer.Import(fds, nfd, ints, ni, w1, h1, stride1, f1, u1);
+ EXPECT_LT(ret, 0);
+ ret = buffer.Import(fds, nfd, ints, ni, w1, h1, stride1, f1, u1);
+ EXPECT_LT(ret, 0);
+ ret = buffer.Import(fds, nfd, ints, ni, w1, h1, stride1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, dataHandle, stride1, 0);
+ EXPECT_EQ(dataHandle->numFds, nfd);
+ EXPECT_EQ(dataHandle->numInts, ni);
+ for (int i = 0; i < nfd; i++)
+ EXPECT_EQ(dataHandle->data[i], fds[i]);
+ for (int i = 0; i < ni; i++)
+ EXPECT_EQ(dataHandle->data[nfd + i], ints[i]);
+ buffer.FreeHandle();
+}
+
+TEST_F(IonBufferUnitTest, TestDuplicate) {
+ IonBuffer buffer;
+ IonBuffer ref;
+ int ints[] = {211, 313, 444};
+ int fds[] = {-1, -1};
+ int ni = sizeof(ints) / sizeof(ints[0]);
+ int nfd = sizeof(fds) / sizeof(fds[0]);
+
+ for (int i = 0; i < nfd; i++) {
+ refHandle->data[i] = fds[i];
+ }
+ for (int i = 0; i < ni; i++) {
+ refHandle->data[i + nfd] = ints[i];
+ }
+
+ EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
+ .Times(1)
+ .WillRepeatedly(DoAll(SetArgPointee<4>(refHandle),
+ SetArgPointee<5>(stride1), Return(0)));
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_create(nfd, ni))
+ .Times(3)
+ .WillOnce(Return(nullptr))
+ .WillRepeatedly(Invoke(native_handle_create_impl));
+ EXPECT_CALL(*GrallocMock::staticObject, registerBuffer(dataHandle))
+ .Times(2)
+ .WillOnce(Return(-1))
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_close(dataHandle))
+ .Times(2);
+ EXPECT_CALL(*GrallocMock::staticObject, native_handle_delete(dataHandle))
+ .Times(2);
+ EXPECT_CALL(*GrallocMock::staticObject, unregisterBuffer(dataHandle))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(*GrallocMock::staticObject, free(refHandle))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+
+ int ret = buffer.Duplicate(&ref);
+ EXPECT_LT(ret, 0);
+ ret = ref.Alloc(w1, h1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ refHandle->numFds = -1;
+ refHandle->numInts = 0;
+ ret = buffer.Duplicate(&ref);
+ EXPECT_LT(ret, 0);
+ refHandle->numFds = nfd;
+ refHandle->numInts = ni;
+ ret = buffer.Duplicate(&ref);
+ EXPECT_LT(ret, 0);
+ ret = buffer.Duplicate(&ref);
+ EXPECT_LT(ret, 0);
+ ret = buffer.Duplicate(&ref);
+ EXPECT_EQ(ret, 0);
+ TestIonBufferState(buffer, w1, h1, 1, f1, u1, dataHandle, stride1, 0);
+ EXPECT_EQ(dataHandle->numFds, nfd);
+ EXPECT_EQ(dataHandle->numInts, ni);
+ for (int i = 0; i < nfd; i++)
+ EXPECT_LT(dataHandle->data[i], 0);
+ for (int i = 0; i < ni; i++)
+ EXPECT_EQ(dataHandle->data[nfd + i], ints[i]);
+ buffer.FreeHandle();
+ ref.FreeHandle();
+}
+
+TEST_F(IonBufferUnitTest, TestLockUnlock) {
+ IonBuffer buffer;
+ const int x = 12;
+ const int y = 24;
+ const int value1 = 17;
+ const int value2 = 25;
+ void* addr1;
+ void** addr = &addr1;
+
+ EXPECT_CALL(*GrallocMock::staticObject, alloc(w1, h1, f1, u1, _, _))
+ .Times(1)
+ .WillRepeatedly(DoAll(SetArgPointee<4>(&handle1),
+ SetArgPointee<5>(stride1), Return(0)));
+ EXPECT_CALL(*GrallocMock::staticObject,
+ lock(&handle1, u2, x, y, w2, h2, addr))
+ .Times(1)
+ .WillRepeatedly(Return(value1));
+ EXPECT_CALL(*GrallocMock::staticObject, unlock(&handle1))
+ .Times(1)
+ .WillRepeatedly(Return(value2));
+ EXPECT_CALL(*GrallocMock::staticObject, free(&handle1))
+ .Times(1)
+ .WillRepeatedly(Return(0));
+
+ int ret = buffer.Alloc(w1, h1, f1, u1);
+ EXPECT_EQ(ret, 0);
+ ret = buffer.Lock(u2, x, y, w2, h2, addr);
+ EXPECT_EQ(ret, value1);
+ ret = buffer.Unlock();
+ EXPECT_EQ(ret, value2);
+ buffer.FreeHandle();
+}
+
+} // namespace