[vulkan] Implement processPipeInitOnce for Fuchsia.

This needs a FIDL implementation as qemu_pipe doesn't work
on Fuchsia.

Test: verified that we get a per-process ID and rcSetPuid is called
Change-Id: I05e7765c39158ba25bc50d4665b201430bc013d4
diff --git a/system/OpenglSystemCommon/ProcessPipe.cpp b/system/OpenglSystemCommon/ProcessPipe.cpp
index ad0527a..5fe9fa3 100644
--- a/system/OpenglSystemCommon/ProcessPipe.cpp
+++ b/system/OpenglSystemCommon/ProcessPipe.cpp
@@ -25,6 +25,12 @@
 #include <pthread.h>
 #include <errno.h>
 
+#ifdef __Fuchsia__
+#include <fuchsia/hardware/goldfish/pipe/cpp/fidl.h>
+#include <lib/fdio/fdio.h>
+#include <lib/zx/vmo.h>
+#endif
+
 static QEMU_PIPE_HANDLE   sProcPipe = 0;
 static pthread_once_t     sProcPipeOnce = PTHREAD_ONCE_INIT;
 // sProcUID is a unique ID per process assigned by the host.
@@ -38,6 +44,79 @@
 // It will fallback to the default path if the host does not support it.
 // Processes are identified by acquiring a per-process 64bit unique ID from the
 // host.
+#ifdef __Fuchsia__
+static void processPipeInitOnce() {
+    int fd = ::open(QEMU_PIPE_PATH, O_RDWR);
+    if (fd < 0) {
+        ALOGE("%s: failed to open " QEMU_PIPE_PATH ": %s",
+              __FUNCTION__, strerror(errno));
+        return;
+    }
+
+    zx::channel channel;
+    zx_status_t status = fdio_get_service_handle(
+        fd, channel.reset_and_get_address());
+    if (status != ZX_OK) {
+        ALOGE("%s: failed to get service handle for " QEMU_PIPE_PATH ": %d",
+              __FUNCTION__, status);
+        close(fd);
+        return;
+    }
+
+    fuchsia::hardware::goldfish::pipe::DeviceSyncPtr device;
+    device.Bind(std::move(channel));
+
+    zx_status_t status2 = ZX_OK;
+    zx::vmo vmo;
+    status = device->GetBuffer(&status2, &vmo);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2);
+        return;
+    }
+
+    size_t len = strlen("pipe:GLProcessPipe");
+    status = vmo.write("pipe:GLProcessPipe", 0, len + 1);
+    if (status != ZX_OK) {
+        ALOGE("%s: failed write pipe name", __FUNCTION__);
+        return;
+    }
+    uint64_t actual;
+    status = device->Write(len + 1, 0, &status2, &actual);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGD("%s: connecting to pipe service failed: %d:%d", __FUNCTION__,
+              status, status2);
+        return;
+    }
+
+    // Send a confirmation int to the host
+    int32_t confirmInt = 100;
+    status = vmo.write(&confirmInt, 0, sizeof(confirmInt));
+    if (status != ZX_OK) {
+        ALOGE("%s: failed write confirm int", __FUNCTION__);
+        return;
+    }
+    status = device->Write(sizeof(confirmInt), 0, &status2, &actual);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGD("%s: failed to send confirm value: %d:%d", __FUNCTION__,
+              status, status2);
+        return;
+    }
+
+    // Ask the host for per-process unique ID
+    status = device->Read(sizeof(sProcUID), 0, &status2, &actual);
+    if (status != ZX_OK || status2 != ZX_OK) {
+        ALOGD("%s: failed to recv per-process ID: %d:%d", __FUNCTION__,
+              status, status2);
+        return;
+    }
+    status = vmo.read(&sProcUID, 0, sizeof(sProcUID));
+    if (status != ZX_OK) {
+        ALOGE("%s: failed read per-process ID: %d", __FUNCTION__, status);
+        return;
+    }
+    sProcPipe = device.Unbind().TakeChannel().release();
+}
+#else
 static void processPipeInitOnce() {
     sProcPipe = qemu_pipe_open("GLProcessPipe");
     if (!qemu_pipe_valid(sProcPipe)) {
@@ -76,6 +155,7 @@
         return;
     }
 }
+#endif
 
 bool processPipeInit(renderControl_encoder_context_t *rcEnc) {
     pthread_once(&sProcPipeOnce, processPipeInitOnce);