1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "GfxStreamAgents.h"
15
16 #include <stdint.h> // for uint32_t
17 #include <stdio.h> // for fprintf
18
19 #include <map> // for map, __ma...
20 #include <utility> // for pair
21
22 #include "host-common/HostmemIdMapping.h" // for android_e...
23 #include "host-common/MultiDisplay.h" // for MultiDisp...
24 #include "host-common/multi_display_agent.h" // for QAndroidM...
25 #include "host-common/vm_operations.h" // for SnapshotC...
26 #include "host-common/window_agent.h" // for WindowMes...
27 #include "host-common/misc.h"
28
29 #ifdef _DEBUG
30 #define DEBUG_LOG(fd, fmt, ...) fprintf(fd, fmt, __VA_ARGS__);
31 #else
32 #define DEBUG_LOG(fd, fmt, ...)
33 #endif
34
35 std::map<uint32_t, android::MultiDisplayInfo> mMultiDisplay;
36
37 using namespace android;
38
39 static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
40 .setMultiDisplay = [](uint32_t id,
41 int32_t x,
42 int32_t y,
43 uint32_t w,
44 uint32_t h,
45 uint32_t dpi,
46 uint32_t flag,
__anon119e3d800102() 47 bool add) -> int {
48 DEBUG_LOG(stderr,
49 "setMultiDisplay (mock): %d, x: %d, y: %d, w: %d, h: %d, "
50 "dpi: %d, flag: %d\n",
51 id, x, y, w, h, dpi, flag);
52 return 0;
53 },
54 .getMultiDisplay = [](uint32_t id,
55 int32_t* x,
56 int32_t* y,
57 uint32_t* w,
58 uint32_t* h,
59 uint32_t* dpi,
60 uint32_t* flag,
__anon119e3d800202() 61 bool* enabled) -> bool {
62 DEBUG_LOG(stderr, "getMultiDisplay (mock) id %u\n", id);
63 if (mMultiDisplay.find(id) == mMultiDisplay.end()) {
64 if (enabled) {
65 *enabled = false;
66 }
67 return false;
68 }
69 if (x) {
70 *x = mMultiDisplay[id].pos_x;
71 }
72 if (y) {
73 *y = mMultiDisplay[id].pos_y;
74 }
75 if (w) {
76 *w = mMultiDisplay[id].width;
77 }
78 if (h) {
79 *h = mMultiDisplay[id].height;
80 }
81 if (dpi) {
82 *dpi = mMultiDisplay[id].dpi;
83 }
84 if (flag) {
85 *flag = mMultiDisplay[id].flag;
86 }
87 if (enabled) {
88 *enabled = mMultiDisplay[id].enabled;
89 }
90 return true;
91 },
92 .getNextMultiDisplay = [](int32_t start_id,
93 uint32_t* id,
94 int32_t* x,
95 int32_t* y,
96 uint32_t* w,
97 uint32_t* h,
98 uint32_t* dpi,
99 uint32_t* flag,
__anon119e3d800302() 100 uint32_t* cb) -> bool {
101 DEBUG_LOG(stderr, "getNextMultiDisplay (mock) start_id %u\n",
102 start_id);
103 uint32_t key;
104 std::map<uint32_t, android::MultiDisplayInfo>::iterator i;
105 if (start_id < 0) {
106 key = 0;
107 } else {
108 key = start_id + 1;
109 }
110 i = mMultiDisplay.lower_bound(key);
111 if (i == mMultiDisplay.end()) {
112 return false;
113 } else {
114 if (id) {
115 *id = i->first;
116 }
117 if (x) {
118 *x = i->second.pos_x;
119 }
120 if (y) {
121 *y = i->second.pos_y;
122 }
123 if (w) {
124 *w = i->second.width;
125 }
126 if (h) {
127 *h = i->second.height;
128 }
129 if (dpi) {
130 *dpi = i->second.dpi;
131 }
132 if (flag) {
133 *flag = i->second.flag;
134 }
135 if (cb) {
136 *cb = i->second.cb;
137 }
138 return true;
139 }
140 },
__anon119e3d800402() 141 .isMultiDisplayEnabled = [](void) -> bool {
142 return mMultiDisplay.size() > 1;
143 },
__anon119e3d800502() 144 .getCombinedDisplaySize = [](uint32_t* width, uint32_t* height) {},
145 .multiDisplayParamValidate = [](uint32_t id,
146 uint32_t w,
147 uint32_t h,
148 uint32_t dpi,
__anon119e3d800602() 149 uint32_t flag) -> bool { return true; },
150 .translateCoordination =
__anon119e3d800702() 151 [](uint32_t* x, uint32_t* y, uint32_t* displayId) -> bool {
152 return true;
153 },
__anon119e3d800802() 154 .setGpuMode = [](bool isGuestMode, uint32_t w, uint32_t h) {},
__anon119e3d800902() 155 .createDisplay = [](uint32_t* displayId) -> int {
156 if (displayId == nullptr) {
157 fprintf(stderr, "null displayId pointer\n");
158 return -1;
159 }
160 if (mMultiDisplay.size() >= MultiDisplay::s_maxNumMultiDisplay) {
161 fprintf(stderr, "cannot create more displays, exceeding limits %d\n",
162 MultiDisplay::s_maxNumMultiDisplay);
163 return -1;
164 }
165 if (mMultiDisplay.find(*displayId) != mMultiDisplay.end()) {
166 return 0;
167 }
168 // displays created by internal rcCommands
169 if (*displayId == MultiDisplay::s_invalidIdMultiDisplay) {
170 for (int i = MultiDisplay::s_displayIdInternalBegin; i < MultiDisplay::s_maxNumMultiDisplay; i++) {
171 if (mMultiDisplay.find(i) == mMultiDisplay.end()) {
172 *displayId = i;
173 break;
174 }
175 }
176 }
177 if (*displayId == MultiDisplay::s_invalidIdMultiDisplay) {
178 fprintf(stderr, "cannot create more internaldisplays, exceeding limits %d\n",
179 MultiDisplay::s_maxNumMultiDisplay - MultiDisplay::s_displayIdInternalBegin);
180 return -1;
181 }
182
183 mMultiDisplay.emplace(*displayId, android::MultiDisplayInfo());
184 return 0;
185 },
__anon119e3d800a02() 186 .destroyDisplay = [](uint32_t displayId) -> int {
187 mMultiDisplay.erase(displayId);
188 return 0;
189 },
190 .setDisplayPose = [](uint32_t displayId,
191 int32_t x,
192 int32_t y,
193 uint32_t w,
194 uint32_t h,
__anon119e3d800b02() 195 uint32_t dpi) -> int {
196 if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
197 fprintf(stderr, "cannot find display %d\n", displayId);
198 return -1;
199 }
200 mMultiDisplay[displayId].pos_x = x;
201 mMultiDisplay[displayId].pos_y = y;
202 mMultiDisplay[displayId].width = w;
203 mMultiDisplay[displayId].height = h;
204 mMultiDisplay[displayId].dpi = dpi;
205 return 0;
206 },
207 .getDisplayPose = [](uint32_t displayId,
208 int32_t* x,
209 int32_t* y,
210 uint32_t* w,
__anon119e3d800c02() 211 uint32_t* h) -> int {
212 if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
213 fprintf(stderr, "cannot find display %d\n", displayId);
214 return -1;
215 }
216 if (x)
217 *x = mMultiDisplay[displayId].pos_x;
218 if (y)
219 *y = mMultiDisplay[displayId].pos_y;
220 if (w)
221 *w = mMultiDisplay[displayId].width;
222 if (h)
223 *h = mMultiDisplay[displayId].height;
224 return 0;
225 },
226 .getDisplayColorBuffer = [](uint32_t displayId,
__anon119e3d800d02() 227 uint32_t* colorBuffer) -> int {
228 if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
229 fprintf(stderr, "cannot find display %d\n", displayId);
230 return -1;
231 }
232 *colorBuffer = mMultiDisplay[displayId].cb;
233 return 0;
234 },
235 .getColorBufferDisplay = [](uint32_t colorBuffer,
__anon119e3d800e02() 236 uint32_t* displayId) -> int {
237 for (const auto& iter : mMultiDisplay) {
238 if (iter.second.cb == colorBuffer) {
239 *displayId = iter.first;
240 return 0;
241 }
242 }
243 return -1;
244 },
245 .setDisplayColorBuffer = [](uint32_t displayId,
__anon119e3d800f02() 246 uint32_t colorBuffer) -> int {
247 if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
248 fprintf(stderr, "cannot find display %d\n", displayId);
249 return -1;
250 }
251 mMultiDisplay[displayId].cb = colorBuffer;
252 return 0;
253 }};
254
255 static bool sIsFolded = false;
256
257 static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
258 .getEmulatorWindow =
__anon119e3d801002() 259 [](void) {
260 DEBUG_LOG(stderr,
261 "window-agent-GfxStream-impl: "
262 ".getEmulatorWindow\n");
263 return (EmulatorWindow*)nullptr;
264 },
265 .rotate90Clockwise =
__anon119e3d801102() 266 [](void) {
267 DEBUG_LOG(stderr,
268 "window-agent-GfxStream-impl: "
269 ".rotate90Clockwise\n");
270 return true;
271 },
272 .rotate =
__anon119e3d801202() 273 [](int rotation) {
274 DEBUG_LOG(stderr,
275 "window-agent-GfxStream-impl: "
276 ".rotate90Clockwise\n");
277 return true;
278 },
279 .getRotation =
__anon119e3d801302() 280 [](void) {
281 DEBUG_LOG(stderr,
282 "window-agent-GfxStream-impl: .getRotation\n");
283 return (int)SKIN_ROTATION_0;
284 },
285 .showMessage =
__anon119e3d801402() 286 [](const char* message, WindowMessageType type, int timeoutMs) {
287 DEBUG_LOG(stderr,
288 "window-agent-GfxStream-impl: .showMessage %s\n",
289 message);
290 },
291 .showMessageWithDismissCallback =
292 [](const char* message,
293 WindowMessageType type,
294 const char* dismissText,
295 void* context,
296 void (*func)(void*),
__anon119e3d801502() 297 int timeoutMs) {
298 DEBUG_LOG(stderr,
299 "window-agent-GfxStream-impl: "
300 ".showMessageWithDismissCallback %s\n",
301 message);
302 },
303 .fold =
__anon119e3d801602() 304 [](bool is_fold) -> bool {
305 DEBUG_LOG(stderr, "window-agent-GfxStream-impl: .fold %d\n",
306 is_fold);
307 sIsFolded = is_fold;
308 return true;
309 },
__anon119e3d801702() 310 .isFolded = [](void) -> bool { return sIsFolded; },
__anon119e3d801802() 311 .getFoldedArea = [](int* x, int* y, int* w, int* h) -> bool {
312 DEBUG_LOG(stderr, "window-agent-GfxStream-impl: .getFoldedArea\n");
313 return true;
314 },
__anon119e3d801902() 315 .updateFoldablePostureIndicator = [](bool) {
316 DEBUG_LOG(stderr, "window-agent-GfxStream-impl: updateFoldablePostureIndicator\n");
317 },
318 .setUIDisplayRegion =
__anon119e3d801a02() 319 [](int x_offset, int y_offset, int w, int h) {
320 DEBUG_LOG(stderr,
321 "window-agent-GfxStream-impl: .setUIDisplayRegion "
322 "%d %d %dx%d\n",
323 x_offset, y_offset, w, h);
324 },
325 .getMultiDisplay = 0,
__anon119e3d801b02() 326 .setNoSkin = [](void) {},
__anon119e3d801c02() 327 .restoreSkin = [](void) {},
328 .updateUIMultiDisplayPage =
__anon119e3d801d02() 329 [](uint32_t id) {
330 DEBUG_LOG(stderr, "updateMultiDisplayPage\n");
331 },
332 .getMonitorRect =
__anon119e3d801e02() 333 [](uint32_t* w, uint32_t* h) -> bool {
334 if (w)
335 *w = 2500;
336 if (h)
337 *h = 1600;
338 return true;
339 },
340 };
341
342 static const QAndroidVmOperations sQAndroidVmOperations = {
__anon119e3d801f02() 343 .vmStop = []() -> bool {
344 DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm stop\n");
345 return true;
346 },
__anon119e3d802002() 347 .vmStart = []() -> bool {
348 DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm start\n");
349 return true;
350 },
351 .vmReset =
__anon119e3d802102() 352 []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm reset\n"); },
353 .vmShutdown =
__anon119e3d802202() 354 []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm reset\n"); },
__anon119e3d802302() 355 .vmPause = []() -> bool {
356 DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm pause\n");
357 return true;
358 },
__anon119e3d802402() 359 .vmResume = []() -> bool {
360 DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm resume\n");
361 return true;
362 },
__anon119e3d802502() 363 .vmIsRunning = []() -> bool {
364 DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm is running\n");
365 return true;
366 },
367 .snapshotList =
__anon119e3d802602() 368 [](void*, LineConsumerCallback, LineConsumerCallback) -> bool {
369 DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot list\n");
370 return true;
371 },
372 .snapshotSave = [](const char* name,
373 void* opaque,
__anon119e3d802702() 374 LineConsumerCallback) -> bool {
375 DEBUG_LOG(stderr, "gfxstream vm ops: snapshot save\n");
376 return true;
377 },
378 .snapshotLoad = [](const char* name,
379 void* opaque,
__anon119e3d802802() 380 LineConsumerCallback) -> bool {
381 DEBUG_LOG(stderr, "gfxstream vm ops: snapshot load\n");
382 return true;
383 },
384 .snapshotDelete = [](const char* name,
385 void* opaque,
__anon119e3d802902() 386 LineConsumerCallback errConsumer) -> bool {
387 DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot delete\n");
388 return true;
389 },
390 .snapshotRemap = [](bool shared,
391 void* opaque,
__anon119e3d802a02() 392 LineConsumerCallback errConsumer) -> bool {
393 DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot remap\n");
394 return true;
395 },
396 .snapshotExport = [](const char* snapshot,
397 const char* dest,
398 void* opaque,
__anon119e3d802b02() 399 LineConsumerCallback errConsumer) -> bool {
400 DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot export image\n");
401 return true;
402 },
403 .setSnapshotCallbacks =
__anon119e3d802c02() 404 [](void* opaque, const SnapshotCallbacks* callbacks) {
405 DEBUG_LOG(stderr,
406 "goldfish-opengl vm ops: set snapshot callbacks\n");
407 },
408 .mapUserBackedRam =
__anon119e3d802d02() 409 [](uint64_t gpa, void* hva, uint64_t size) {
410 DEBUG_LOG(stderr, "%s: map user backed ram\n", __func__);
411 },
412 .unmapUserBackedRam =
__anon119e3d802e02() 413 [](uint64_t gpa, uint64_t size) {
414 DEBUG_LOG(stderr, "%s: unmap user backed ram\n", __func__);
415 },
416 .getVmConfiguration =
__anon119e3d802f02() 417 [](VmConfiguration* out) {
418 DEBUG_LOG(stderr,
419 "goldfish-opengl vm ops: get vm configuration\n");
420 },
421 .setFailureReason =
__anon119e3d803002() 422 [](const char* name, int failureReason) {
423 DEBUG_LOG(stderr,
424 "goldfish-opengl vm ops: set failure reason\n");
425 },
426 .setExiting =
__anon119e3d803102() 427 []() {
428 DEBUG_LOG(stderr, "goldfish-opengl vm ops: set exiting\n");
429 },
430 .allowRealAudio =
__anon119e3d803202() 431 [](bool allow) {
432 DEBUG_LOG(stderr,
433 "goldfish-opengl vm ops: allow real audio\n");
434 },
435 .physicalMemoryGetAddr =
__anon119e3d803302() 436 [](uint64_t gpa) {
437 DEBUG_LOG(stderr, "%s: physmemGetAddr\n", __func__);
438 return (void*)nullptr;
439 },
440 .isRealAudioAllowed =
__anon119e3d803402() 441 [](void) {
442 DEBUG_LOG(stderr,
443 "goldfish-opengl vm ops: is real audiop allowed\n");
444 return true;
445 },
446 .setSkipSnapshotSave =
__anon119e3d803502() 447 [](bool used) {
448 DEBUG_LOG(stderr,
449 "goldfish-opengl vm ops: set skip snapshot save\n");
450 },
451 .isSnapshotSaveSkipped =
__anon119e3d803602() 452 []() {
453 DEBUG_LOG(stderr,
454 "goldfish-opengl vm ops: is snapshot save "
455 "skipped\n");
456 return false;
457 },
458 .hostmemRegister = android_emulation_hostmem_register,
459 .hostmemUnregister = android_emulation_hostmem_unregister,
460 .hostmemGetInfo = android_emulation_hostmem_get_info,
461 };
462
463 namespace android {
464 namespace emulation {
465
466 const QAndroidVmOperations* const
android_get_QAndroidVmOperations() const467 GfxStreamAndroidConsoleFactory::android_get_QAndroidVmOperations() const {
468 return &sQAndroidVmOperations;
469 }
470
471 const QAndroidMultiDisplayAgent* const
android_get_QAndroidMultiDisplayAgent() const472 GfxStreamAndroidConsoleFactory::android_get_QAndroidMultiDisplayAgent() const {
473 return &sMultiDisplayAgent;
474 }
475
476 const QAndroidEmulatorWindowAgent* const
android_get_QAndroidEmulatorWindowAgent() const477 GfxStreamAndroidConsoleFactory::android_get_QAndroidEmulatorWindowAgent()
478 const {
479 return &sQAndroidEmulatorWindowAgent;
480 }
481 } // namespace emulation
482 } // namespace android
483