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