blob: 56f1e528ee73b1821fdc14c78485eda265d3091d [file] [log] [blame]
Yahan Zhou41050592016-07-28 16:31:59 -07001/*
2* Copyright (C) 2016 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
Yilong Li46669082020-01-14 16:22:57 -080017#include "ProcessPipe.h"
Yahan Zhoue8cf63d2016-09-22 12:33:50 -070018#include "renderControl_enc.h"
Roman Kiryanov5fb783e2020-04-28 13:22:29 -070019
20#define ALLOW_DEPRECATED_QEMU_PIPE_HEADERS
21#include <qemu_pipe.h>
Yahan Zhoue8cf63d2016-09-22 12:33:50 -070022
Luca Stefani1cb647a2019-03-07 21:58:17 +010023#if PLATFORM_SDK_VERSION < 26
Logan Chiend7bf00d2018-09-21 06:30:09 +000024#include <cutils/log.h>
Luca Stefani1cb647a2019-03-07 21:58:17 +010025#else
26#include <log/log.h>
27#endif
Yahan Zhou41050592016-07-28 16:31:59 -070028#include <pthread.h>
Lingfeng Yange38d15c2018-09-24 16:24:01 -070029#include <errno.h>
Yahan Zhou41050592016-07-28 16:31:59 -070030
David Reveman5e2e8422019-05-02 15:48:15 -040031#ifdef __Fuchsia__
Yilong Lib373b392019-10-17 15:30:14 -070032#include <fuchsia/hardware/goldfish/cpp/fidl.h>
David Reveman5e2e8422019-05-02 15:48:15 -040033#include <lib/zx/vmo.h>
John Bauman8153a442019-10-16 15:41:17 -070034
35#include "services/service_connector.h"
36
David Reveman8bc32552019-06-28 10:32:41 -040037static QEMU_PIPE_HANDLE sProcDevice = 0;
Lingfeng Yang9c26ebf2019-12-30 09:14:49 -080038#else // __Fuchsia__
39
40#include "VirtioGpuPipeStream.h"
41static VirtioGpuPipeStream* sVirtioGpuPipeStream = 0;
42
43#endif // !__Fuchsia__
David Reveman5e2e8422019-05-02 15:48:15 -040044
Lingfeng Yange38d15c2018-09-24 16:24:01 -070045static QEMU_PIPE_HANDLE sProcPipe = 0;
Yahan Zhou41050592016-07-28 16:31:59 -070046static pthread_once_t sProcPipeOnce = PTHREAD_ONCE_INIT;
47// sProcUID is a unique ID per process assigned by the host.
48// It is different from getpid().
49static uint64_t sProcUID = 0;
Lingfeng Yang9c26ebf2019-12-30 09:14:49 -080050static volatile HostConnectionType sConnType = HOST_CONNECTION_VIRTIO_GPU_PIPE;
Yahan Zhou41050592016-07-28 16:31:59 -070051
Yahan Zhoue8cf63d2016-09-22 12:33:50 -070052// processPipeInitOnce is used to generate a process unique ID (puid).
Yahan Zhou41050592016-07-28 16:31:59 -070053// processPipeInitOnce will only be called at most once per process.
54// Use it with pthread_once for thread safety.
55// The host associates resources with process unique ID (puid) for memory cleanup.
56// It will fallback to the default path if the host does not support it.
57// Processes are identified by acquiring a per-process 64bit unique ID from the
58// host.
David Reveman5e2e8422019-05-02 15:48:15 -040059#ifdef __Fuchsia__
60static void processPipeInitOnce() {
John Bauman8153a442019-10-16 15:41:17 -070061 zx::channel channel(GetConnectToServiceFunction()(QEMU_PIPE_PATH));
62 if (!channel) {
63 ALOGE("%s: failed to open " QEMU_PIPE_PATH,
64 __FUNCTION__);
David Reveman5e2e8422019-05-02 15:48:15 -040065 return;
66 }
67
Yilong Lib373b392019-10-17 15:30:14 -070068 fuchsia::hardware::goldfish::PipeDeviceSyncPtr device;
David Reveman5e2e8422019-05-02 15:48:15 -040069 device.Bind(std::move(channel));
70
Yilong Lib373b392019-10-17 15:30:14 -070071 fuchsia::hardware::goldfish::PipeSyncPtr pipe;
David Reveman8bc32552019-06-28 10:32:41 -040072 device->OpenPipe(pipe.NewRequest());
73
John Bauman8153a442019-10-16 15:41:17 -070074 zx_status_t status, status2 = ZX_OK;
David Reveman5e2e8422019-05-02 15:48:15 -040075 zx::vmo vmo;
David Reveman8bc32552019-06-28 10:32:41 -040076 status = pipe->GetBuffer(&status2, &vmo);
David Reveman5e2e8422019-05-02 15:48:15 -040077 if (status != ZX_OK || status2 != ZX_OK) {
78 ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2);
79 return;
80 }
81
82 size_t len = strlen("pipe:GLProcessPipe");
83 status = vmo.write("pipe:GLProcessPipe", 0, len + 1);
84 if (status != ZX_OK) {
85 ALOGE("%s: failed write pipe name", __FUNCTION__);
86 return;
87 }
88 uint64_t actual;
David Reveman8bc32552019-06-28 10:32:41 -040089 status = pipe->Write(len + 1, 0, &status2, &actual);
David Reveman5e2e8422019-05-02 15:48:15 -040090 if (status != ZX_OK || status2 != ZX_OK) {
91 ALOGD("%s: connecting to pipe service failed: %d:%d", __FUNCTION__,
92 status, status2);
93 return;
94 }
95
David Reveman8bc32552019-06-28 10:32:41 -040096 // Send a confirmation int to the host and get per-process unique ID back
David Reveman5e2e8422019-05-02 15:48:15 -040097 int32_t confirmInt = 100;
98 status = vmo.write(&confirmInt, 0, sizeof(confirmInt));
99 if (status != ZX_OK) {
100 ALOGE("%s: failed write confirm int", __FUNCTION__);
101 return;
102 }
David Reveman8bc32552019-06-28 10:32:41 -0400103 status = pipe->Call(sizeof(confirmInt), 0, sizeof(sProcUID), 0, &status2, &actual);
David Reveman5e2e8422019-05-02 15:48:15 -0400104 if (status != ZX_OK || status2 != ZX_OK) {
David Reveman8bc32552019-06-28 10:32:41 -0400105 ALOGD("%s: failed to get per-process ID: %d:%d", __FUNCTION__,
David Reveman5e2e8422019-05-02 15:48:15 -0400106 status, status2);
107 return;
108 }
109 status = vmo.read(&sProcUID, 0, sizeof(sProcUID));
110 if (status != ZX_OK) {
111 ALOGE("%s: failed read per-process ID: %d", __FUNCTION__, status);
112 return;
113 }
David Reveman8bc32552019-06-28 10:32:41 -0400114 sProcDevice = device.Unbind().TakeChannel().release();
115 sProcPipe = pipe.Unbind().TakeChannel().release();
David Reveman5e2e8422019-05-02 15:48:15 -0400116}
Lingfeng Yang9c26ebf2019-12-30 09:14:49 -0800117#else // __Fuchsia__
118
119static void sQemuPipeInit() {
Yahan Zhou41050592016-07-28 16:31:59 -0700120 sProcPipe = qemu_pipe_open("GLProcessPipe");
Lingfeng Yange38d15c2018-09-24 16:24:01 -0700121 if (!qemu_pipe_valid(sProcPipe)) {
Yahan Zhou41050592016-07-28 16:31:59 -0700122 sProcPipe = 0;
123 ALOGW("Process pipe failed");
124 return;
125 }
126 // Send a confirmation int to the host
127 int32_t confirmInt = 100;
128 ssize_t stat = 0;
129 do {
Lingfeng Yange38d15c2018-09-24 16:24:01 -0700130 stat =
131 qemu_pipe_write(sProcPipe, (const char*)&confirmInt,
Yahan Zhou41050592016-07-28 16:31:59 -0700132 sizeof(confirmInt));
133 } while (stat < 0 && errno == EINTR);
134
135 if (stat != sizeof(confirmInt)) { // failed
Lingfeng Yange38d15c2018-09-24 16:24:01 -0700136 qemu_pipe_close(sProcPipe);
Yahan Zhou41050592016-07-28 16:31:59 -0700137 sProcPipe = 0;
138 ALOGW("Process pipe failed");
139 return;
140 }
141
142 // Ask the host for per-process unique ID
143 do {
Lingfeng Yange38d15c2018-09-24 16:24:01 -0700144 stat =
145 qemu_pipe_read(sProcPipe, (char*)&sProcUID,
146 sizeof(sProcUID));
Lingfeng Yangd0b2a8a2019-08-07 00:59:55 +0000147 } while (stat < 0 && (errno == EINTR || errno == EAGAIN));
Yahan Zhou41050592016-07-28 16:31:59 -0700148
149 if (stat != sizeof(sProcUID)) {
Lingfeng Yange38d15c2018-09-24 16:24:01 -0700150 qemu_pipe_close(sProcPipe);
Yahan Zhou41050592016-07-28 16:31:59 -0700151 sProcPipe = 0;
152 sProcUID = 0;
153 ALOGW("Process pipe failed");
154 return;
155 }
156}
157
Lingfeng Yang9c26ebf2019-12-30 09:14:49 -0800158static void processPipeInitOnce() {
Lingfeng Yangfe14fdb2020-01-02 10:22:09 -0800159#if defined(HOST_BUILD) || !defined(GOLDFISH_VULKAN)
Lingfeng Yang9c26ebf2019-12-30 09:14:49 -0800160 sQemuPipeInit();
161#else // HOST_BUILD
162 switch (sConnType) {
163 // TODO: Move those over too
164 case HOST_CONNECTION_QEMU_PIPE:
165 case HOST_CONNECTION_ADDRESS_SPACE:
166 case HOST_CONNECTION_TCP:
167 case HOST_CONNECTION_VIRTIO_GPU:
168 sQemuPipeInit();
169 break;
170 case HOST_CONNECTION_VIRTIO_GPU_PIPE: {
171 sVirtioGpuPipeStream = new VirtioGpuPipeStream(4096);
172 sProcUID = sVirtioGpuPipeStream->initProcessPipe();
173 break;
174 }
175 }
176#endif // !HOST_BUILD
177}
178#endif // !__Fuchsia__
179
180bool processPipeInit(HostConnectionType connType, renderControl_encoder_context_t *rcEnc) {
181 sConnType = connType;
Yahan Zhou41050592016-07-28 16:31:59 -0700182 pthread_once(&sProcPipeOnce, processPipeInitOnce);
Yilong Li46669082020-01-14 16:22:57 -0800183 bool pipeHandleInvalid = !sProcPipe;
184#ifndef __Fuchsia__
185 pipeHandleInvalid = pipeHandleInvalid && !sVirtioGpuPipeStream;
186#endif // !__Fuchsia__
187 if (pipeHandleInvalid) return false;
Yahan Zhoue8cf63d2016-09-22 12:33:50 -0700188 rcEnc->rcSetPuid(rcEnc, sProcUID);
189 return true;
Lingfeng Yang88c170c2016-11-30 00:52:35 +0000190}