Add GraphicBuffer over binder test and fix a crash in unflatten logic
Test: GraphicBuffer_test GraphicBufferOverBinder_test
Bug: None
Change-Id: Idf00fcb740661adc1e1bb41dc2d78ece4f589c95
diff --git a/libs/ui/tests/GraphicBufferOverBinder_test.cpp b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
new file mode 100644
index 0000000..7c0a44a
--- /dev/null
+++ b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 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 "GraphicBufferOverBinder_test"
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <ui/BufferHubBuffer.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Log.h>
+
+namespace android {
+
+constexpr uint32_t kTestWidth = 1024;
+constexpr uint32_t kTestHeight = 1;
+constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint32_t kTestLayerCount = 1;
+constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+static const String16 kTestServiceName = String16("GraphicBufferOverBinderTestService");
+enum GraphicBufferOverBinderTestServiceCode {
+ GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+ GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER,
+};
+
+class GraphicBufferOverBinderTestService : public BBinder {
+public:
+ GraphicBufferOverBinderTestService() {
+ // GraphicBuffer
+ mGraphicBuffer = new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount,
+ kTestUsage);
+ ALOGI("mGraphicBuffer id %" PRIi32, mGraphicBuffer->getBufferId());
+
+ // BufferHub-backed GraphicBuffer
+ std::unique_ptr<BufferHubBuffer> bufferHubBuffer =
+ BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+ kTestUsage, /*userMetadataSize=*/0);
+ mBufferhubBackedGraphicBuffer = new GraphicBuffer(std::move(bufferHubBuffer));
+ if (!mBufferhubBackedGraphicBuffer->isBufferHubBuffer()) {
+ ALOGE("Failed to back GraphicBuffer with BufferHub.");
+ }
+ if (bufferHubBuffer != nullptr) {
+ ALOGE("Failed to move BufferHubBuffer to GraphicBuffer");
+ }
+ ALOGI("mBufferhubBackedGraphicBuffer id %" PRIi32,
+ mBufferhubBackedGraphicBuffer->getBufferId());
+ }
+
+ ~GraphicBufferOverBinderTestService() = default;
+
+ virtual status_t onTransact(uint32_t code, const Parcel& /*data*/, Parcel* reply,
+ uint32_t /*flags*/ = 0) {
+ switch (code) {
+ case GRAPHIC_BUFFER: {
+ return reply->write(*mGraphicBuffer);
+ }
+ case GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER: {
+ return reply->write(*mBufferhubBackedGraphicBuffer);
+ }
+ default:
+ return UNKNOWN_TRANSACTION;
+ };
+ }
+
+protected:
+ sp<GraphicBuffer> mGraphicBuffer;
+ sp<GraphicBuffer> mBufferhubBackedGraphicBuffer;
+};
+
+static int runBinderServer() {
+ ProcessState::self()->startThreadPool();
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<GraphicBufferOverBinderTestService> service = new GraphicBufferOverBinderTestService;
+ sm->addService(kTestServiceName, service, false);
+
+ ALOGI("Binder server running...");
+
+ while (true) {
+ int stat, retval;
+ retval = wait(&stat);
+ if (retval == -1 && errno == ECHILD) {
+ break;
+ }
+ }
+
+ ALOGI("Binder server exiting...");
+ return 0;
+}
+
+class GraphicBufferOverBinderTest : public ::testing::TestWithParam<uint32_t> {
+protected:
+ virtual void SetUp() {
+ mService = defaultServiceManager()->getService(kTestServiceName);
+ if (mService == nullptr) {
+ ALOGE("Failed to connect to the test service.");
+ return;
+ }
+
+ ALOGI("Binder service is ready for client.");
+ }
+
+ status_t GetGraphicBuffer(sp<GraphicBuffer>* outBuf, uint32_t opCode) {
+ Parcel data;
+ Parcel reply;
+ status_t error = mService->transact(opCode, data, &reply);
+ if (error != NO_ERROR) {
+ ALOGE("Failed to get graphic buffer over binder, error=%d.", error);
+ return error;
+ }
+
+ *outBuf = new GraphicBuffer();
+ return reply.read(**outBuf);
+ }
+
+private:
+ sp<IBinder> mService;
+};
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferOverBinder) {
+ sp<GraphicBuffer> gb;
+ EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER), OK);
+ EXPECT_NE(gb, nullptr);
+ EXPECT_FALSE(gb->isBufferHubBuffer());
+ void* vaddr;
+ EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+ EXPECT_EQ(gb->unlock(), OK);
+}
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferFromBufferHubBufferOverBinder) {
+ sp<GraphicBuffer> gb;
+ EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER), NO_ERROR);
+ EXPECT_NE(gb, nullptr);
+ EXPECT_TRUE(gb->isBufferHubBuffer());
+ void* vaddr;
+ EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+ EXPECT_EQ(gb->unlock(), OK);
+}
+
+} // namespace android
+
+int main(int argc, char** argv) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ android::ProcessState::self()->startThreadPool();
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+
+ } else {
+ ALOGI("Test process pid: %d.", pid);
+ return android::runBinderServer();
+ }
+}