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 static 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,
__anon99f56eaf0102() 47                               bool add) -> int {
48             return 0;
49         },
50         .getMultiDisplay = [](uint32_t id,
51                               int32_t* x,
52                               int32_t* y,
53                               uint32_t* w,
54                               uint32_t* h,
55                               uint32_t* dpi,
56                               uint32_t* flag,
__anon99f56eaf0202() 57                               bool* enabled) -> bool {
58             if (mMultiDisplay.find(id) == mMultiDisplay.end()) {
59                 if (enabled) {
60                     *enabled = false;
61                 }
62                 return false;
63             }
64             if (x) {
65                 *x = mMultiDisplay[id].pos_x;
66             }
67             if (y) {
68                 *y = mMultiDisplay[id].pos_y;
69             }
70             if (w) {
71                 *w = mMultiDisplay[id].width;
72             }
73             if (h) {
74                 *h = mMultiDisplay[id].height;
75             }
76             if (dpi) {
77                 *dpi = mMultiDisplay[id].dpi;
78             }
79             if (flag) {
80                 *flag = mMultiDisplay[id].flag;
81             }
82             if (enabled) {
83                 *enabled = mMultiDisplay[id].enabled;
84             }
85             return true;
86         },
87         .getNextMultiDisplay = [](int32_t start_id,
88                                   uint32_t* id,
89                                   int32_t* x,
90                                   int32_t* y,
91                                   uint32_t* w,
92                                   uint32_t* h,
93                                   uint32_t* dpi,
94                                   uint32_t* flag,
__anon99f56eaf0302() 95                                   uint32_t* cb) -> bool {
96             uint32_t key;
97             std::map<uint32_t, android::MultiDisplayInfo>::iterator i;
98             if (start_id < 0) {
99                 key = 0;
100             } else {
101                 key = start_id + 1;
102             }
103             i = mMultiDisplay.lower_bound(key);
104             if (i == mMultiDisplay.end()) {
105                 return false;
106             } else {
107                 if (id) {
108                     *id = i->first;
109                 }
110                 if (x) {
111                     *x = i->second.pos_x;
112                 }
113                 if (y) {
114                     *y = i->second.pos_y;
115                 }
116                 if (w) {
117                     *w = i->second.width;
118                 }
119                 if (h) {
120                     *h = i->second.height;
121                 }
122                 if (dpi) {
123                     *dpi = i->second.dpi;
124                 }
125                 if (flag) {
126                     *flag = i->second.flag;
127                 }
128                 if (cb) {
129                     *cb = i->second.cb;
130                 }
131                 return true;
132             }
133         },
__anon99f56eaf0402() 134         .isMultiDisplayEnabled = [](void) -> bool {
135             return mMultiDisplay.size() > 1;
136         },
__anon99f56eaf0502() 137         .getCombinedDisplaySize = [](uint32_t* width, uint32_t* height) {},
138         .multiDisplayParamValidate = [](uint32_t id,
139                                         uint32_t w,
140                                         uint32_t h,
141                                         uint32_t dpi,
__anon99f56eaf0602() 142                                         uint32_t flag) -> bool { return true; },
143         .translateCoordination =
__anon99f56eaf0702() 144                 [](uint32_t* x, uint32_t* y, uint32_t* displayId) -> bool {
145             return true;
146         },
__anon99f56eaf0802() 147         .setGpuMode = [](bool isGuestMode, uint32_t w, uint32_t h) {},
__anon99f56eaf0902() 148         .createDisplay = [](uint32_t* displayId) -> int {
149             if (displayId == nullptr) {
150                 ERR("cannot create display, null displayId pointer");
151                 return -1;
152             }
153             if (mMultiDisplay.size() >= MultiDisplay::s_maxNumMultiDisplay) {
154                 ERR("cannot create more displays, exceeding limits %d",
155                         MultiDisplay::s_maxNumMultiDisplay);
156                 return -1;
157             }
158             if (mMultiDisplay.find(*displayId) != mMultiDisplay.end()) {
159                 return 0;
160             }
161             // displays created by internal rcCommands
162             if (*displayId == MultiDisplay::s_invalidIdMultiDisplay) {
163                 for (int i = MultiDisplay::s_displayIdInternalBegin; i < MultiDisplay::s_maxNumMultiDisplay; i++) {
164                     if (mMultiDisplay.find(i) == mMultiDisplay.end()) {
165                         *displayId = i;
166                         break;
167                     }
168                 }
169             }
170             if (*displayId == MultiDisplay::s_invalidIdMultiDisplay) {
171                 ERR("cannot create more internaldisplays, exceeding limits %d",
172                         MultiDisplay::s_maxNumMultiDisplay - MultiDisplay::s_displayIdInternalBegin);
173                 return -1;
174             }
175 
176             mMultiDisplay.emplace(*displayId, android::MultiDisplayInfo());
177             return 0;
178         },
__anon99f56eaf0a02() 179         .destroyDisplay = [](uint32_t displayId) -> int {
180             mMultiDisplay.erase(displayId);
181             return 0;
182         },
183         .setDisplayPose = [](uint32_t displayId,
184                              int32_t x,
185                              int32_t y,
186                              uint32_t w,
187                              uint32_t h,
__anon99f56eaf0b02() 188                              uint32_t dpi) -> int {
189             if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
190                 ERR("cannot find display %d", displayId);
191                 return -1;
192             }
193             mMultiDisplay[displayId].pos_x = x;
194             mMultiDisplay[displayId].pos_y = y;
195             mMultiDisplay[displayId].width = w;
196             mMultiDisplay[displayId].height = h;
197             mMultiDisplay[displayId].dpi = dpi;
198             return 0;
199         },
200         .getDisplayPose = [](uint32_t displayId,
201                              int32_t* x,
202                              int32_t* y,
203                              uint32_t* w,
__anon99f56eaf0c02() 204                              uint32_t* h) -> int {
205             if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
206                 ERR("cannot find display %d", displayId);
207                 return -1;
208             }
209             if (x)
210                 *x = mMultiDisplay[displayId].pos_x;
211             if (y)
212                 *y = mMultiDisplay[displayId].pos_y;
213             if (w)
214                 *w = mMultiDisplay[displayId].width;
215             if (h)
216                 *h = mMultiDisplay[displayId].height;
217             return 0;
218         },
219         .getDisplayColorBuffer = [](uint32_t displayId,
__anon99f56eaf0d02() 220                                     uint32_t* colorBuffer) -> int {
221             if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
222                 ERR("cannot find display %d", displayId);
223                 return -1;
224             }
225             *colorBuffer = mMultiDisplay[displayId].cb;
226             return 0;
227         },
228         .getColorBufferDisplay = [](uint32_t colorBuffer,
__anon99f56eaf0e02() 229                                     uint32_t* displayId) -> int {
230             for (const auto& iter : mMultiDisplay) {
231                 if (iter.second.cb == colorBuffer) {
232                     *displayId = iter.first;
233                     return 0;
234                 }
235             }
236             return -1;
237         },
238         .setDisplayColorBuffer = [](uint32_t displayId,
__anon99f56eaf0f02() 239                                     uint32_t colorBuffer) -> int {
240             if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
241                 ERR("Unable to set display color buffer for non existing display: %d", displayId);
242                 return -1;
243             }
244             mMultiDisplay[displayId].cb = colorBuffer;
245             return 0;
246         },
__anon99f56eaf1002() 247        .isPixelFold = [] () {
248            return false;
249        },
250     };
251 
252 static bool sIsFolded = false;
253 
254 static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
255         .getEmulatorWindow =
__anon99f56eaf1102() 256                 [](void) {
257                     DEBUG_LOG(stderr,
258                             "window-agent-GfxStream-impl: "
259                             ".getEmulatorWindow\n");
260                     return (EmulatorWindow*)nullptr;
261                 },
262         .rotate90Clockwise =
__anon99f56eaf1202() 263                 [](void) {
264                     DEBUG_LOG(stderr,
265                             "window-agent-GfxStream-impl: "
266                             ".rotate90Clockwise\n");
267                     return true;
268                 },
269         .rotate =
__anon99f56eaf1302() 270                 [](int rotation) {
271                     DEBUG_LOG(stderr,
272                             "window-agent-GfxStream-impl: "
273                             ".rotate90Clockwise\n");
274                     return true;
275                 },
276         .getRotation =
__anon99f56eaf1402() 277                 [](void) {
278                     DEBUG_LOG(stderr,
279                             "window-agent-GfxStream-impl: .getRotation\n");
280                     return (int)SKIN_ROTATION_0;
281                 },
282         .showMessage =
__anon99f56eaf1502() 283                 [](const char* message, WindowMessageType type, int timeoutMs) {
284                     DEBUG_LOG(stderr,
285                             "window-agent-GfxStream-impl: .showMessage %s\n",
286                             message);
287                 },
288         .showMessageWithDismissCallback =
289                 [](const char* message,
290                    WindowMessageType type,
291                    const char* dismissText,
292                    void* context,
293                    void (*func)(void*),
__anon99f56eaf1602() 294                    int timeoutMs) {
295                     DEBUG_LOG(stderr,
296                             "window-agent-GfxStream-impl: "
297                             ".showMessageWithDismissCallback %s\n",
298                             message);
299                 },
300         .fold =
__anon99f56eaf1702() 301                 [](bool is_fold) -> bool {
302                     DEBUG_LOG(stderr, "window-agent-GfxStream-impl: .fold %d\n",
303                             is_fold);
304                     sIsFolded = is_fold;
305                     return true;
306                 },
__anon99f56eaf1802() 307         .isFolded = [](void) -> bool { return sIsFolded; },
__anon99f56eaf1902() 308         .getFoldedArea = [](int* x, int* y, int* w, int* h) -> bool {
309             DEBUG_LOG(stderr, "window-agent-GfxStream-impl: .getFoldedArea\n");
310             return true;
311         },
__anon99f56eaf1a02() 312         .updateFoldablePostureIndicator = [](bool) {
313             DEBUG_LOG(stderr, "window-agent-GfxStream-impl: updateFoldablePostureIndicator\n");
314         },
315         .setUIDisplayRegion =
__anon99f56eaf1b02() 316                 [](int x_offset, int y_offset, int w, int h, bool ignoreOrientation) {
317                     DEBUG_LOG(stderr,
318                             "window-agent-GfxStream-impl: .setUIDisplayRegion "
319                             "%d %d %dx%d\n",
320                             x_offset, y_offset, w, h);
321                 },
322         .getMultiDisplay = 0,
__anon99f56eaf1c02() 323         .setNoSkin = [](void) {},
__anon99f56eaf1d02() 324         .restoreSkin = [](void) {},
325         .updateUIMultiDisplayPage =
__anon99f56eaf1e02() 326                 [](uint32_t id) {
327                     DEBUG_LOG(stderr, "updateMultiDisplayPage\n");
328                 },
329         .getMonitorRect =
__anon99f56eaf1f02() 330                 [](uint32_t* w, uint32_t* h) -> bool {
331                     if (w)
332                         *w = 2500;
333                     if (h)
334                         *h = 1600;
335                     return true;
336                 },
337 };
338 
339 static const QAndroidVmOperations sQAndroidVmOperations =
340     {
__anon99f56eaf2002() 341         .vmStop = []() -> bool {
342             DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm stop\n");
343             return true;
344         },
__anon99f56eaf2102() 345         .vmStart = []() -> bool {
346             DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm start\n");
347             return true;
348         },
__anon99f56eaf2202() 349         .vmReset = []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm reset\n"); },
__anon99f56eaf2302() 350         .vmShutdown = []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm reset\n"); },
__anon99f56eaf2402() 351         .vmPause = []() -> bool {
352             DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm pause\n");
353             return true;
354         },
__anon99f56eaf2502() 355         .vmResume = []() -> bool {
356             DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm resume\n");
357             return true;
358         },
__anon99f56eaf2602() 359         .vmIsRunning = []() -> bool {
360             DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm is running\n");
361             return true;
362         },
__anon99f56eaf2702() 363         .snapshotList = [](void*, LineConsumerCallback, LineConsumerCallback) -> bool {
364             DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot list\n");
365             return true;
366         },
__anon99f56eaf2802() 367         .snapshotSave = [](const char* name, void* opaque, LineConsumerCallback) -> bool {
368             DEBUG_LOG(stderr, "gfxstream vm ops: snapshot save\n");
369             return true;
370         },
__anon99f56eaf2902() 371         .snapshotLoad = [](const char* name, void* opaque, LineConsumerCallback) -> bool {
372             DEBUG_LOG(stderr, "gfxstream vm ops: snapshot load\n");
373             return true;
374         },
375         .snapshotDelete = [](const char* name, void* opaque,
__anon99f56eaf2a02() 376                              LineConsumerCallback errConsumer) -> bool {
377             DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot delete\n");
378             return true;
379         },
__anon99f56eaf2b02() 380         .snapshotRemap = [](bool shared, void* opaque, LineConsumerCallback errConsumer) -> bool {
381             DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot remap\n");
382             return true;
383         },
384         .snapshotExport = [](const char* snapshot, const char* dest, void* opaque,
__anon99f56eaf2c02() 385                              LineConsumerCallback errConsumer) -> bool {
386             DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot export image\n");
387             return true;
388         },
389         .setSnapshotCallbacks =
__anon99f56eaf2d02() 390             [](void* opaque, const SnapshotCallbacks* callbacks) {
391                 DEBUG_LOG(stderr, "goldfish-opengl vm ops: set snapshot callbacks\n");
392             },
393         .mapUserBackedRam =
__anon99f56eaf2e02() 394             [](uint64_t gpa, void* hva, uint64_t size) {
395                 DEBUG_LOG(stderr, "%s: map user backed ram\n", __func__);
396             },
397         .unmapUserBackedRam =
__anon99f56eaf2f02() 398             [](uint64_t gpa, uint64_t size) {
399                 DEBUG_LOG(stderr, "%s: unmap user backed ram\n", __func__);
400             },
401         .getVmConfiguration =
__anon99f56eaf3002() 402             [](VmConfiguration* out) {
403                 DEBUG_LOG(stderr, "goldfish-opengl vm ops: get vm configuration\n");
404             },
405         .setFailureReason =
__anon99f56eaf3102() 406             [](const char* name, int failureReason) {
407                 DEBUG_LOG(stderr, "goldfish-opengl vm ops: set failure reason\n");
408             },
__anon99f56eaf3202() 409         .setExiting = []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: set exiting\n"); },
410         .allowRealAudio =
__anon99f56eaf3302() 411             [](bool allow) { DEBUG_LOG(stderr, "goldfish-opengl vm ops: allow real audio\n"); },
412         .physicalMemoryGetAddr =
__anon99f56eaf3402() 413             [](uint64_t gpa) {
414                 DEBUG_LOG(stderr, "%s: physmemGetAddr\n", __func__);
415                 return (void*)nullptr;
416             },
417         .isRealAudioAllowed =
__anon99f56eaf3502() 418             [](void) {
419                 DEBUG_LOG(stderr, "goldfish-opengl vm ops: is real audiop allowed\n");
420                 return true;
421             },
422         .setSkipSnapshotSave =
__anon99f56eaf3602() 423             [](bool used) {
424                 DEBUG_LOG(stderr, "goldfish-opengl vm ops: set skip snapshot save\n");
425             },
426         .isSnapshotSaveSkipped =
__anon99f56eaf3702() 427             []() {
428                 DEBUG_LOG(stderr,
429                           "goldfish-opengl vm ops: is snapshot save "
430                           "skipped\n");
431                 return false;
432             },
433         .hostmemRegister = android_emulation_hostmem_register,
434         .hostmemUnregister = android_emulation_hostmem_unregister,
435         .hostmemGetInfo = android_emulation_hostmem_get_info,
436 #ifdef GFXSTREAM_BUILD_WITH_SNAPSHOT_SUPPORT
437         .setSkipSnapshotSaveReason =
__anon99f56eaf3802() 438             [](SnapshotSkipReason reason) {
439                 DEBUG_LOG(stderr,
440                         "goldfish-opengl vm ops: set skip snapshot save reason"
441                         "skipped\n");
442             },
443         .getSkipSnapshotSaveReason =
__anon99f56eaf3902() 444             []() {
445                 DEBUG_LOG(stderr,
446                         "goldfish-opengl vm ops: get skip snapshot save "
447                         "reason\n");
448                 return SNAPSHOT_SKIP_UNKNOWN;
449             },
450         .setStatSnapshotUseVulkan =
__anon99f56eaf3a02() 451             []() {
452                 DEBUG_LOG(stderr,
453                         "goldfish-opengl vm ops: set stat snapshot use Vulkan"
454                         "skipped\n");
455             },
456         .snapshotUseVulkan =
__anon99f56eaf3b02() 457             []() {
458                 DEBUG_LOG(stderr,
459                         "goldfish-opengl vm ops: get stat snapshot use Vulkan"
460                         "skipped\n");
461                 return false;
462             },
463 #endif
464 };
465 
466 namespace android {
467 namespace emulation {
468 
469 const QAndroidVmOperations* const
android_get_QAndroidVmOperations() const470 GfxStreamGraphicsAgentFactory::android_get_QAndroidVmOperations() const {
471     return &sQAndroidVmOperations;
472 }
473 
474 const QAndroidMultiDisplayAgent* const
android_get_QAndroidMultiDisplayAgent() const475 GfxStreamGraphicsAgentFactory::android_get_QAndroidMultiDisplayAgent() const {
476     return &sMultiDisplayAgent;
477 }
478 
479 const QAndroidEmulatorWindowAgent* const
android_get_QAndroidEmulatorWindowAgent() const480 GfxStreamGraphicsAgentFactory::android_get_QAndroidEmulatorWindowAgent()
481         const {
482     return &sQAndroidEmulatorWindowAgent;
483 }
484 }  // namespace emulation
485 }  // namespace android
486