1 /*
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
17 #include "ProcessPipe.h"
18
19 #include <errno.h>
20 #include <log/log.h>
21 #include <pthread.h>
22 #include <qemu_pipe_bp.h>
23
24 #include "HostConnection.h"
25 #include "renderControl_enc.h"
26
27 #ifndef __Fuchsia__
28
29 #include "VirtioGpuPipeStream.h"
30 static VirtioGpuPipeStream* sVirtioGpuPipeStream = 0;
31 static int sStreamHandle = -1;
32
33 #endif // !__Fuchsia__
34
35 static QEMU_PIPE_HANDLE sProcPipe = 0;
36 // sProcUID is a unique ID per process assigned by the host.
37 // It is different from getpid().
38 static uint64_t sProcUID = 0;
39 static HostConnectionType sConnType = HOST_CONNECTION_VIRTIO_GPU_PIPE;
40
41 static uint32_t* sSeqnoPtr = 0;
42
43 // Meant to be called only once per process.
initSeqno(void)44 static void initSeqno(void) {
45 // So why do we reinitialize here? It's for testing purposes only;
46 // we have a unit test that exercise the case where this sequence
47 // number is reset as a result of guest process kill.
48 if (sSeqnoPtr) delete sSeqnoPtr;
49 sSeqnoPtr = new uint32_t;
50 *sSeqnoPtr = 0;
51 }
52
53 namespace {
54
55 static std::mutex sNeedInitMutex;
56 static bool sNeedInit = true;
57
58 } // namespace
59
60 #ifndef __Fuchsia__
61
sQemuPipeInit()62 static void sQemuPipeInit() {
63 sProcPipe = qemu_pipe_open("GLProcessPipe");
64 if (!qemu_pipe_valid(sProcPipe)) {
65 sProcPipe = 0;
66 ALOGW("Process pipe failed");
67 return;
68 }
69 // Send a confirmation int to the host
70 int32_t confirmInt = 100;
71 if (qemu_pipe_write_fully(sProcPipe, &confirmInt, sizeof(confirmInt))) { // failed
72 qemu_pipe_close(sProcPipe);
73 sProcPipe = 0;
74 ALOGW("Process pipe failed");
75 return;
76 }
77
78 // Ask the host for per-process unique ID
79 if (qemu_pipe_read_fully(sProcPipe, &sProcUID, sizeof(sProcUID))) {
80 qemu_pipe_close(sProcPipe);
81 sProcPipe = 0;
82 sProcUID = 0;
83 ALOGW("Process pipe failed");
84 return;
85 }
86 }
87
88 #endif // !__Fuchsia__
89
processPipeDoInit(uint32_t noRenderControlEnc)90 static void processPipeDoInit(uint32_t noRenderControlEnc) {
91 initSeqno();
92
93 // No need to setup auxiliary pipe stream in this case
94 if (noRenderControlEnc) return;
95
96 #if defined(__Fuchsia__)
97 // Note: sProcUID is not initialized.
98 ALOGE("Fuchsia: requires noRenderControlEnc");
99 abort();
100 #else
101 switch (sConnType) {
102 // TODO: Move those over too
103 case HOST_CONNECTION_QEMU_PIPE:
104 case HOST_CONNECTION_ADDRESS_SPACE:
105 sQemuPipeInit();
106 break;
107 case HOST_CONNECTION_VIRTIO_GPU_PIPE:
108 case HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE: {
109 sVirtioGpuPipeStream = new VirtioGpuPipeStream(4096, sStreamHandle);
110 sProcUID = sVirtioGpuPipeStream->initProcessPipe();
111 break;
112 }
113 }
114 #endif
115 }
116
processPipeInit(int streamHandle,HostConnectionType connType,uint32_t noRenderControlEnc)117 bool processPipeInit(int streamHandle, HostConnectionType connType, uint32_t noRenderControlEnc) {
118 sConnType = connType;
119 #ifndef __Fuchsia__
120 sStreamHandle = streamHandle;
121 #endif // !__Fuchsia
122
123 {
124 std::lock_guard<std::mutex> lock(sNeedInitMutex);
125
126 if (sNeedInit) {
127 sNeedInit = false;
128 processPipeDoInit(noRenderControlEnc);
129
130 if (noRenderControlEnc) {
131 return true;
132 }
133
134 #ifndef __Fuchsia__
135 if (!sProcPipe && !sVirtioGpuPipeStream) {
136 return false;
137 }
138 #endif
139 }
140 }
141
142 return true;
143 }
144
getPuid()145 uint64_t getPuid() {
146 return sProcUID;
147 }
148
processPipeRestart()149 void processPipeRestart() {
150 std::lock_guard<std::mutex> lock(sNeedInitMutex);
151
152 ALOGW("%s: restarting process pipe\n", __func__);
153 bool isPipe = false;
154
155 switch (sConnType) {
156 // TODO: Move those over too
157 case HOST_CONNECTION_QEMU_PIPE:
158 case HOST_CONNECTION_ADDRESS_SPACE:
159 isPipe = true;
160 break;
161 case HOST_CONNECTION_VIRTIO_GPU_PIPE:
162 case HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE: {
163 isPipe = false;
164 break;
165 }
166 }
167
168 sProcUID = 0;
169
170 if (isPipe) {
171 if (qemu_pipe_valid(sProcPipe)) {
172 qemu_pipe_close(sProcPipe);
173 sProcPipe = 0;
174 }
175 } else {
176 #ifndef __Fuchsia__
177 if (sVirtioGpuPipeStream) {
178 delete sVirtioGpuPipeStream;
179 sVirtioGpuPipeStream = nullptr;
180 }
181 #endif
182 }
183
184 if (sConnType == HOST_CONNECTION_VIRTIO_GPU_PIPE ||
185 sConnType == HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE) {
186 VirtGpuDevice::resetInstance();
187 }
188
189 sNeedInit = true;
190 }
191
refreshHostConnection()192 void refreshHostConnection() {
193 HostConnection* hostConn = HostConnection::get();
194 ExtendedRCEncoderContext* rcEnc = hostConn->rcEncoder();
195 rcEnc->rcSetPuid(rcEnc, sProcUID);
196 }
197
getSeqnoPtrForProcess()198 uint32_t* getSeqnoPtrForProcess() {
199 // It's assumed process pipe state has already been initialized.
200 return sSeqnoPtr;
201 }
202