• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 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 #include "HostConnection.h"
17 
18 #include "GoldfishAddressSpaceStream.h"
19 #include "GrallocGoldfish.h"
20 #include "GrallocMinigbm.h"
21 #include "VirtioGpuAddressSpaceStream.h"
22 #include "aemu/base/AndroidHealthMonitor.h"
23 #include "aemu/base/AndroidHealthMonitorConsumerBasic.h"
24 #include "aemu/base/threads/AndroidThread.h"
25 
26 #if defined(__ANDROID__)
27 #include "ANativeWindowAndroid.h"
28 #include "android-base/properties.h"
29 #endif
30 
31 #include "aemu/base/Process.h"
32 
33 using gfxstream::guest::CreateHealthMonitor;
34 using gfxstream::guest::HealthMonitor;
35 using gfxstream::guest::HealthMonitorConsumerBasic;
36 using gfxstream::guest::IOStream;
37 using gfxstream::GoldfishGralloc;
38 using gfxstream::MinigbmGralloc;
39 
40 #include "VkEncoder.h"
41 #include "AddressSpaceStream.h"
42 
43 using gfxstream::vk::VkEncoder;
44 
45 #include <unistd.h>
46 
47 #include "ProcessPipe.h"
48 #include "QemuPipeStream.h"
49 #include "ThreadInfo.h"
50 
51 using gfxstream::guest::getCurrentThreadId;
52 
53 #include "VirtGpu.h"
54 #include "VirtioGpuPipeStream.h"
55 #include "virtgpu_drm.h"
56 
57 #if defined(__linux__) || defined(__ANDROID__)
58 #include <fstream>
59 #include <string>
60 #include <unistd.h>
61 
62 static const size_t kPageSize = getpagesize();
63 #else
64 constexpr size_t kPageSize = PAGE_SIZE;
65 #endif
66 
67 #undef LOG_TAG
68 #define LOG_TAG "HostConnection"
69 #include <cutils/log.h>
70 
71 #define STREAM_BUFFER_SIZE  (4*1024*1024)
72 #define STREAM_PORT_NUM     22468
73 
74 constexpr const auto kEglProp = "ro.hardware.egl";
75 
getGlobalHealthMonitor()76 HealthMonitor<>* getGlobalHealthMonitor() {
77     // Initialize HealthMonitor
78     // Rather than inject as a construct arg, we keep it as a static variable in the .cpp
79     // to avoid setting up dependencies in other repos (external/qemu)
80     static HealthMonitorConsumerBasic sHealthMonitorConsumerBasic;
81     static std::unique_ptr<HealthMonitor<>> sHealthMonitor = CreateHealthMonitor(sHealthMonitorConsumerBasic);
82     return sHealthMonitor.get();
83 }
84 
getConnectionTypeFromProperty(enum VirtGpuCapset capset)85 static HostConnectionType getConnectionTypeFromProperty(enum VirtGpuCapset capset) {
86 #if defined(__Fuchsia__) || defined(LINUX_GUEST_BUILD)
87     return HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE;
88 #else
89     std::string transport;
90 
91 #if defined(__ANDROID__)
92     transport = android::base::GetProperty("ro.boot.hardware.gltransport", "");
93 #else
94     const char* transport_envvar = getenv("GFXSTREAM_TRANSPORT");
95     if (transport_envvar != nullptr) {
96         transport = std::string(transport_envvar);
97     }
98 #endif
99 
100     if (transport.empty()) {
101 #if defined(__ANDROID__)
102         return HOST_CONNECTION_QEMU_PIPE;
103 #else
104         return HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE;
105 #endif
106     }
107 
108     if (transport == "asg") {
109         return HOST_CONNECTION_ADDRESS_SPACE;
110     }
111     if (transport == "pipe") {
112         return HOST_CONNECTION_QEMU_PIPE;
113     }
114 
115     if (transport == "virtio-gpu-asg" || transport == "virtio-gpu-pipe") {
116         std::string egl;
117 #if defined(__ANDROID__)
118         egl = android::base::GetProperty(kEglProp, "");
119 #endif
120         // ANGLE doesn't work well without ASG, particularly if HostComposer uses a pipe
121         // transport and VK uses ASG.
122         if (capset == kCapsetGfxStreamVulkan || egl == "angle") {
123             return HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE;
124         } else {
125             return HOST_CONNECTION_VIRTIO_GPU_PIPE;
126         }
127     }
128 
129     return HOST_CONNECTION_QEMU_PIPE;
130 #endif
131 }
132 
getGrallocTypeFromProperty()133 static GrallocType getGrallocTypeFromProperty() {
134     std::string value;
135 
136 #if defined(__ANDROID__)
137     value = android::base::GetProperty("ro.hardware.gralloc", "");
138 #endif
139 
140     if (value.empty()) {
141         return GRALLOC_TYPE_RANCHU;
142     }
143     if (value == "minigbm") {
144         return GRALLOC_TYPE_MINIGBM;
145     }
146     if (value == "ranchu") {
147         return GRALLOC_TYPE_RANCHU;
148     }
149     return GRALLOC_TYPE_RANCHU;
150 }
151 
152 #if defined(__ANDROID__)
153 static GoldfishGralloc m_goldfishGralloc;
154 #endif
155 
HostConnection()156 HostConnection::HostConnection()
157     : exitUncleanly(false),
158       m_hostExtensions(),
159       m_noHostError(true),
160       m_rendernodeFd(-1) { }
161 
~HostConnection()162 HostConnection::~HostConnection()
163 {
164     // round-trip to ensure that queued commands have been processed
165     // before process pipe closure is detected.
166 #if GFXSTREAM_GUEST_USE_GLES
167     if (m_rcEnc && !exitUncleanly) {
168         (void)m_rcEnc->rcGetRendererVersion(m_rcEnc.get());
169     }
170 #endif
171 
172     if (m_grallocType == GRALLOC_TYPE_MINIGBM) {
173         delete m_grallocHelper;
174     }
175 
176     if (m_vkEnc) {
177         m_vkEnc->decRef();
178     }
179 
180     if (m_stream) {
181         m_stream->decRef();
182     }
183 }
184 
185 
186 // static
connect(enum VirtGpuCapset capset)187 std::unique_ptr<HostConnection> HostConnection::connect(enum VirtGpuCapset capset) {
188     const enum HostConnectionType connType = getConnectionTypeFromProperty(capset);
189     uint32_t noRenderControlEnc = 0;
190 
191     // Use "new" to access a non-public constructor.
192     auto con = std::unique_ptr<HostConnection>(new HostConnection);
193     con->m_connectionType = connType;
194 
195     switch (connType) {
196         case HOST_CONNECTION_ADDRESS_SPACE: {
197 #if defined(__ANDROID__) || defined(__Fuchsia__)
198             auto stream = createGoldfishAddressSpaceStream(STREAM_BUFFER_SIZE, getGlobalHealthMonitor());
199             if (!stream) {
200                 ALOGE("Failed to create AddressSpaceStream for host connection\n");
201                 return nullptr;
202             }
203             con->m_stream = stream;
204 #else
205             ALOGE("Fatal: HOST_CONNECTION_ADDRESS_SPACE not supported on this host.");
206             abort();
207 #endif
208             con->m_grallocType = GRALLOC_TYPE_RANCHU;
209 #if defined(__ANDROID__)
210             con->m_grallocHelper = &m_goldfishGralloc;
211 #endif
212             break;
213         }
214 #if !defined(__Fuchsia__)
215         case HOST_CONNECTION_QEMU_PIPE: {
216             auto stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
217             if (!stream) {
218                 ALOGE("Failed to create QemuPipeStream for host connection\n");
219                 return nullptr;
220             }
221             if (stream->connect() < 0) {
222                 ALOGE("Failed to connect to host (QemuPipeStream)\n");
223                 return nullptr;
224             }
225             con->m_grallocType = GRALLOC_TYPE_RANCHU;
226             con->m_stream = stream;
227 #if defined(__ANDROID__)
228             con->m_grallocHelper = &m_goldfishGralloc;
229 #endif
230             break;
231         }
232 #endif
233         case HOST_CONNECTION_VIRTIO_GPU_PIPE: {
234             auto stream = new VirtioGpuPipeStream(STREAM_BUFFER_SIZE);
235             if (!stream) {
236                 ALOGE("Failed to create VirtioGpu for host connection\n");
237                 return nullptr;
238             }
239             if (stream->connect() < 0) {
240                 ALOGE("Failed to connect to host (VirtioGpu)\n");
241                 return nullptr;
242             }
243             con->m_grallocType = getGrallocTypeFromProperty();
244             auto rendernodeFd = stream->getRendernodeFd();
245             con->m_stream = stream;
246             con->m_rendernodeFd = rendernodeFd;
247 #if defined(__ANDROID__)
248             switch (con->m_grallocType) {
249                 case GRALLOC_TYPE_RANCHU:
250                     con->m_grallocHelper = &m_goldfishGralloc;
251                     break;
252                 case GRALLOC_TYPE_MINIGBM: {
253                     MinigbmGralloc* m = new MinigbmGralloc;
254                     m->setFd(rendernodeFd);
255                     con->m_grallocHelper = m;
256                     break;
257                 }
258                 default:
259                     ALOGE("Fatal: Unknown gralloc type 0x%x\n", con->m_grallocType);
260                     abort();
261             }
262 #endif
263             break;
264         }
265         case HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE: {
266             // Use kCapsetGfxStreamVulkan for now, Ranchu HWC needs to be modified to pass in
267             // right capset.
268             auto device = VirtGpuDevice::getInstance(kCapsetGfxStreamVulkan);
269             auto deviceHandle = device->getDeviceHandle();
270             auto stream =
271                 createVirtioGpuAddressSpaceStream(kCapsetGfxStreamVulkan, getGlobalHealthMonitor());
272             if (!stream) {
273                 ALOGE("Failed to create virtgpu AddressSpaceStream\n");
274                 return nullptr;
275             }
276             con->m_grallocType = getGrallocTypeFromProperty();
277             con->m_stream = stream;
278             con->m_rendernodeFd = deviceHandle;
279 #if defined(__ANDROID__)
280             switch (con->m_grallocType) {
281                 case GRALLOC_TYPE_RANCHU:
282                     con->m_grallocHelper = &m_goldfishGralloc;
283                     break;
284                 case GRALLOC_TYPE_MINIGBM: {
285                     MinigbmGralloc* m = new gfxstream::MinigbmGralloc;
286                     m->setFd(deviceHandle);
287                     con->m_grallocHelper = m;
288                     break;
289                 }
290                 default:
291                     ALOGE("Fatal: Unknown gralloc type 0x%x\n", con->m_grallocType);
292                     abort();
293             }
294 #endif
295             break;
296         }
297         default:
298             break;
299     }
300 
301 #if defined(__ANDROID__)
302     con->m_anwHelper = new gfxstream::ANativeWindowHelperAndroid();
303 #else
304     // Host builds are expected to set an ANW helper for testing.
305 #endif
306     con->m_syncHelper.reset(gfxstream::createPlatformSyncHelper());
307 
308     // send zero 'clientFlags' to the host.
309     unsigned int *pClientFlags =
310             (unsigned int *)con->m_stream->allocBuffer(sizeof(unsigned int));
311     *pClientFlags = 0;
312     con->m_stream->commitBuffer(sizeof(unsigned int));
313 
314     if (capset == kCapsetGfxStreamMagma) {
315         noRenderControlEnc = 1;
316     } else if (capset == kCapsetGfxStreamVulkan) {
317         VirtGpuDevice* instance = VirtGpuDevice::getInstance(kCapsetGfxStreamVulkan);
318         auto caps = instance->getCaps();
319         noRenderControlEnc = caps.vulkanCapset.noRenderControlEnc;
320     }
321 
322     auto fd = (connType == HOST_CONNECTION_VIRTIO_GPU_ADDRESS_SPACE) ? con->m_rendernodeFd : -1;
323     processPipeInit(fd, connType, noRenderControlEnc);
324     return con;
325 }
326 
get()327 HostConnection* HostConnection::get() { return getWithThreadInfo(getEGLThreadInfo(), kCapsetNone); }
328 
getOrCreate(enum VirtGpuCapset capset)329 HostConnection* HostConnection::getOrCreate(enum VirtGpuCapset capset) {
330     return getWithThreadInfo(getEGLThreadInfo(), capset);
331 }
332 
getWithThreadInfo(EGLThreadInfo * tinfo,enum VirtGpuCapset capset)333 HostConnection* HostConnection::getWithThreadInfo(EGLThreadInfo* tinfo, enum VirtGpuCapset capset) {
334     // Get thread info
335     if (!tinfo) {
336         return NULL;
337     }
338 
339     if (tinfo->hostConn == NULL) {
340         tinfo->hostConn = HostConnection::createUnique(capset);
341     }
342 
343     return tinfo->hostConn.get();
344 }
345 
exit()346 void HostConnection::exit() {
347     EGLThreadInfo *tinfo = getEGLThreadInfo();
348     if (!tinfo) {
349         return;
350     }
351 
352     tinfo->hostConn.reset();
353 }
354 
exitUnclean()355 void HostConnection::exitUnclean() {
356     EGLThreadInfo *tinfo = getEGLThreadInfo();
357     if (!tinfo) {
358         return;
359     }
360 
361     tinfo->hostConn->exitUncleanly = true;
362     tinfo->hostConn.reset();
363 }
364 
365 // static
createUnique(enum VirtGpuCapset capset)366 std::unique_ptr<HostConnection> HostConnection::createUnique(enum VirtGpuCapset capset) {
367     return connect(capset);
368 }
369 
vkEncoder()370 VkEncoder* HostConnection::vkEncoder() {
371     if (!m_vkEnc) {
372         m_vkEnc = new VkEncoder(m_stream, getGlobalHealthMonitor());
373     }
374     return m_vkEnc;
375 }
376