• 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 #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