1 /*
2 * Copyright (C) 2024 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 <array>
18 #include <mutex>
19 #include <string_view>
20 #include <unordered_set>
21 #include <vector>
22 
23 #include <cutils/native_handle.h>
24 #include <log/log.h>
25 #include <sync/sync.h>
26 
27 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
28 #include <aidl/android/hardware/graphics/common/ChromaSiting.h>
29 #include <aidl/android/hardware/graphics/common/Compression.h>
30 #include <aidl/android/hardware/graphics/common/Interlaced.h>
31 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
32 #include <aidl/android/hardware/graphics/common/StandardMetadataType.h>
33 
34 #include <android/hardware/graphics/mapper/IMapper.h>
35 #include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
36 
37 #include <debug.h>
38 #include <FormatConversions.h>
39 #include <goldfish_address_space.h>
40 #include <gralloc_cb_bp.h>
41 
42 #include "CbExternalMetadata.h"
43 #include "DebugLevel.h"
44 #include "HostConnectionSession.h"
45 
46 #ifndef DRM_FORMAT_MOD_LINEAR
47 #define DRM_FORMAT_MOD_LINEAR 0
48 #endif
49 
50 namespace aahgc = ::aidl::android::hardware::graphics::common;
51 using aahgc::BufferUsage;
52 using aahgc::ChromaSiting;
53 using aahgc::Interlaced;
54 using aahgc::PixelFormat;
55 using aahgc::StandardMetadataType;
56 
57 using ::android::hardware::graphics::mapper::MetadataReader;
58 using ::android::hardware::graphics::mapper::MetadataWriter;
59 
60 namespace {
61 constexpr size_t kMetadataBufferInitialSize = 1024;
62 constexpr uint32_t kCPU_READ_MASK = static_cast<uint32_t>(BufferUsage::CPU_READ_MASK);
63 constexpr uint32_t kCPU_WRITE_MASK = static_cast<uint32_t>(BufferUsage::CPU_WRITE_MASK);
64 
65 using namespace std::literals;
66 
67 const char kStandardMetadataTypeStr[] = "android.hardware.graphics.common.StandardMetadataType";
68 const std::string_view kStandardMetadataTypeTag(kStandardMetadataTypeStr, sizeof(kStandardMetadataTypeStr) - 1);
69 const std::string_view kChromaSitingTag = "android.hardware.graphics.common.ChromaSiting"sv;
70 const std::string_view kCompressionTag = "android.hardware.graphics.common.Compression"sv;
71 const std::string_view kInterlacedTag = "android.hardware.graphics.common.Interlaced"sv;
72 const std::string_view kPlaneLayoutComponentTypeTag = "android.hardware.graphics.common.PlaneLayoutComponentType"sv;
73 
arraySize(T (&)[SIZE])74 template<class T, size_t SIZE> constexpr size_t arraySize(T (&)[SIZE]) { return SIZE; }
75 
getPixelFormat(const cb_handle_t & cb)76 PixelFormat getPixelFormat(const cb_handle_t& cb) {
77     return static_cast<PixelFormat>(cb.format);
78 }
79 
isYuvFormat(const PixelFormat format)80 bool isYuvFormat(const PixelFormat format) {
81     switch (format) {
82     case PixelFormat::YCRCB_420_SP:
83     case PixelFormat::YV12:
84     case PixelFormat::YCBCR_420_888:
85     case PixelFormat::YCBCR_P010:
86         return true;
87 
88     default:
89         return false;
90     }
91 }
92 
getFormatChromaSiting(const PixelFormat format)93 ChromaSiting getFormatChromaSiting(const PixelFormat format) {
94     return isYuvFormat(format) ? ChromaSiting::SITED_INTERSTITIAL : ChromaSiting::NONE;
95 }
96 
getExternalMetadata(const cb_handle_t & cb)97 CbExternalMetadata& getExternalMetadata(const cb_handle_t& cb) {
98     CbExternalMetadata& m = *reinterpret_cast<CbExternalMetadata*>(
99         cb.getBufferPtr() + cb.externalMetadataOffset);
100     LOG_ALWAYS_FATAL_IF(m.magic != CbExternalMetadata::kMagicValue);
101     return m;
102 }
103 
getID(const cb_handle_t & cb)104 uint64_t getID(const cb_handle_t& cb) {
105     return getExternalMetadata(cb).bufferID;
106 }
107 
waitFenceFd(const int fd,const char * logname)108 int waitFenceFd(const int fd, const char* logname) {
109     const int warningTimeout = 5000;
110     if (sync_wait(fd, warningTimeout) < 0) {
111         if (errno == ETIME) {
112             ALOGW("%s: fence %d didn't signal in %d ms", logname, fd, warningTimeout);
113             if (sync_wait(fd, -1) < 0) {
114                 return errno;
115             } else {
116                 return 0;
117             }
118         } else {
119             return errno;
120         }
121     } else {
122         return 0;
123     }
124 }
125 
126 const AIMapper_MetadataTypeDescription kMetadataTypeDescriptionList[] = {
127     {
128         .metadataType = {
129             .name = kStandardMetadataTypeStr,
130             .value = static_cast<int64_t>(StandardMetadataType::BUFFER_ID),
131         },
132         .isGettable = true,
133         .isSettable = false,
134     },
135     {
136         .metadataType = {
137             .name = kStandardMetadataTypeStr,
138             .value = static_cast<int64_t>(StandardMetadataType::NAME),
139         },
140         .isGettable = true,
141         .isSettable = false,
142     },
143     {
144         .metadataType = {
145             .name = kStandardMetadataTypeStr,
146             .value = static_cast<int64_t>(StandardMetadataType::WIDTH),
147         },
148         .isGettable = true,
149         .isSettable = false,
150     },
151     {
152         .metadataType = {
153             .name = kStandardMetadataTypeStr,
154             .value = static_cast<int64_t>(StandardMetadataType::HEIGHT),
155         },
156         .isGettable = true,
157         .isSettable = false,
158     },
159     {
160         .metadataType = {
161             .name = kStandardMetadataTypeStr,
162             .value = static_cast<int64_t>(StandardMetadataType::LAYER_COUNT),
163         },
164         .isGettable = true,
165         .isSettable = false,
166     },
167     {
168         .metadataType = {
169             .name = kStandardMetadataTypeStr,
170             .value = static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_REQUESTED),
171         },
172         .isGettable = true,
173         .isSettable = false,
174     },
175     {
176         .metadataType = {
177             .name = kStandardMetadataTypeStr,
178             .value = static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_FOURCC),
179         },
180         .isGettable = true,
181         .isSettable = false,
182     },
183     {
184         .metadataType = {
185             .name = kStandardMetadataTypeStr,
186             .value = static_cast<int64_t>(StandardMetadataType::PIXEL_FORMAT_MODIFIER),
187         },
188         .isGettable = true,
189         .isSettable = false,
190     },
191     {
192         .metadataType = {
193             .name = kStandardMetadataTypeStr,
194             .value = static_cast<int64_t>(StandardMetadataType::USAGE),
195         },
196         .isGettable = true,
197         .isSettable = false,
198     },
199     {
200         .metadataType = {
201             .name = kStandardMetadataTypeStr,
202             .value = static_cast<int64_t>(StandardMetadataType::ALLOCATION_SIZE),
203         },
204         .isGettable = true,
205         .isSettable = false,
206     },
207     {
208         .metadataType = {
209             .name = kStandardMetadataTypeStr,
210             .value = static_cast<int64_t>(StandardMetadataType::PROTECTED_CONTENT),
211         },
212         .isGettable = true,
213         .isSettable = false,
214     },
215     {
216         .metadataType = {
217             .name = kStandardMetadataTypeStr,
218             .value = static_cast<int64_t>(StandardMetadataType::COMPRESSION),
219         },
220         .isGettable = true,
221         .isSettable = false,
222     },
223     {
224         .metadataType = {
225             .name = kStandardMetadataTypeStr,
226             .value = static_cast<int64_t>(StandardMetadataType::INTERLACED),
227         },
228         .isGettable = true,
229         .isSettable = false,
230     },
231     {
232         .metadataType = {
233             .name = kStandardMetadataTypeStr,
234             .value = static_cast<int64_t>(StandardMetadataType::CHROMA_SITING),
235         },
236         .isGettable = true,
237         .isSettable = false,
238     },
239     {
240         .metadataType = {
241             .name = kStandardMetadataTypeStr,
242             .value = static_cast<int64_t>(StandardMetadataType::PLANE_LAYOUTS),
243         },
244         .isGettable = true,
245         .isSettable = false,
246     },
247     {
248         .metadataType = {
249             .name = kStandardMetadataTypeStr,
250             .value = static_cast<int64_t>(StandardMetadataType::CROP),
251         },
252         .isGettable = true,
253         .isSettable = false,
254     },
255     {
256         .metadataType = {
257             .name = kStandardMetadataTypeStr,
258             .value = static_cast<int64_t>(StandardMetadataType::DATASPACE),
259         },
260         .isGettable = true,
261         .isSettable = true,
262     },
263     {
264         .metadataType = {
265             .name = kStandardMetadataTypeStr,
266             .value = static_cast<int64_t>(StandardMetadataType::BLEND_MODE),
267         },
268         .isGettable = true,
269         .isSettable = true,
270     },
271     {
272         .metadataType = {
273             .name = kStandardMetadataTypeStr,
274             .value = static_cast<int64_t>(StandardMetadataType::SMPTE2086),
275         },
276         .isGettable = true,
277         .isSettable = true,
278     },
279     {
280         .metadataType = {
281             .name = kStandardMetadataTypeStr,
282             .value = static_cast<int64_t>(StandardMetadataType::CTA861_3),
283         },
284         .isGettable = true,
285         .isSettable = true,
286     },
287     {
288         .metadataType = {
289             .name = kStandardMetadataTypeStr,
290             .value = static_cast<int64_t>(StandardMetadataType::STRIDE),
291         },
292         .isGettable = true,
293         .isSettable = false,
294     },
295 };
296 
297 struct GoldfishMapper {
GoldfishMapper__anon555456480111::GoldfishMapper298     GoldfishMapper()
299             : mHostConn(HostConnection::createUnique(kCapsetNone))
300             , mDebugLevel(getDebugLevel()) {
301         GoldfishAddressSpaceHostMemoryAllocator hostMemoryAllocator(false);
302         LOG_ALWAYS_FATAL_IF(!hostMemoryAllocator.is_opened(),
303             "GoldfishAddressSpaceHostMemoryAllocator failed to open");
304 
305         GoldfishAddressSpaceBlock bufferBits;
306         LOG_ALWAYS_FATAL_IF(hostMemoryAllocator.hostMalloc(&bufferBits, 256),
307                             "hostMalloc failed");
308 
309         mPhysAddrToOffset = bufferBits.physAddr() - bufferBits.offset();
310         hostMemoryAllocator.hostFree(&bufferBits);
311 
312         static GoldfishMapper* s_instance;
313 
314         mMapper.version = AIMAPPER_VERSION_5;
315         mMapper.v5.importBuffer = [](const native_handle_t* handle,
316                                      buffer_handle_t* outBufferHandle) {
317             return s_instance->importBuffer(handle, outBufferHandle);
318         };
319         mMapper.v5.freeBuffer = [](buffer_handle_t buffer) {
320             return s_instance->freeBuffer(buffer);
321         };
322         mMapper.v5.getTransportSize = &getTransportSize;
323         mMapper.v5.lock = [](buffer_handle_t buffer, uint64_t cpuUsage,
324                              ARect accessRegion, int acquireFence,
325                              void** outData){
326             return s_instance->lock(buffer, cpuUsage, accessRegion,
327                                     acquireFence, outData);
328         };
329         mMapper.v5.unlock = [](buffer_handle_t buffer, int* releaseFence) {
330             return s_instance->unlock(buffer, releaseFence);
331         };
332         mMapper.v5.flushLockedBuffer = [](buffer_handle_t buffer) {
333             return s_instance->flushLockedBuffer(buffer);
334         };
335         mMapper.v5.rereadLockedBuffer = [](buffer_handle_t buffer) {
336             return s_instance->rereadLockedBuffer(buffer);
337         };
338         mMapper.v5.getMetadata = [](const buffer_handle_t buffer,
339                                     const AIMapper_MetadataType metadataType,
340                                     void* const destBuffer, const size_t destBufferSize) {
341             return s_instance->getMetadata(buffer, metadataType,
342                                            destBuffer, destBufferSize);
343         };
344         mMapper.v5.getStandardMetadata = [](const buffer_handle_t buffer,
345                                             const int64_t standardMetadataType,
346                                             void* const destBuffer,
347                                             const size_t destBufferSize) {
348             return s_instance->getStandardMetadata(buffer, standardMetadataType,
349                                                    destBuffer, destBufferSize);
350         };
351         mMapper.v5.setMetadata = [](const buffer_handle_t buffer,
352                                     const AIMapper_MetadataType metadataType,
353                                     const void* const metadata, const size_t metadataSize) {
354             return s_instance->setMetadata(buffer, metadataType,
355                                            metadata, metadataSize);
356         };
357         mMapper.v5.setStandardMetadata = [](const buffer_handle_t buffer,
358                                             const int64_t standardMetadataType,
359                                             const void* const metadata,
360                                             const size_t metadataSize) {
361             return s_instance->setStandardMetadata(buffer, standardMetadataType,
362                                                    metadata, metadataSize);
363         };
364         mMapper.v5.listSupportedMetadataTypes = &listSupportedMetadataTypes;
365         mMapper.v5.dumpBuffer = [](const buffer_handle_t buffer,
366                                    const AIMapper_DumpBufferCallback dumpBufferCallback,
367                                    void* const context) {
368             return s_instance->dumpBuffer(buffer, dumpBufferCallback, context);
369         };
370         mMapper.v5.dumpAllBuffers = [](AIMapper_BeginDumpBufferCallback beginDumpCallback,
371                                        AIMapper_DumpBufferCallback dumpBufferCallback,
372                                        void* context){
373             return s_instance->dumpAllBuffers(beginDumpCallback, dumpBufferCallback,
374                                               context);
375         };
376         mMapper.v5.getReservedRegion = [](const buffer_handle_t buffer,
377                                           void** const outReservedRegion,
378                                           uint64_t* const outReservedSize) {
379             return s_instance->getReservedRegion(buffer, outReservedRegion,
380                                                  outReservedSize);
381         };
382 
383         s_instance = this;
384     }
385 
getAIMapper__anon555456480111::GoldfishMapper386     AIMapper& getAIMapper() {
387         return mMapper;
388     }
389 
390 private:
importBuffer__anon555456480111::GoldfishMapper391     AIMapper_Error importBuffer(const native_handle_t* const handle,
392                                 buffer_handle_t* const outBufferHandle) {
393         if (!handle) {
394             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
395         }
396         native_handle_t* const imported = native_handle_clone(handle);
397         if (!imported) {
398             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
399         }
400         cb_handle_t* const cb = cb_handle_t::from(imported);
401         if (!cb) {
402             native_handle_close(imported);
403             native_handle_delete(imported);
404             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
405         }
406 
407         if (cb->mmapedSize) {
408             const int bufferFd = cb->bufferFd;
409             LOG_ALWAYS_FATAL_IF(bufferFd < 0);
410 
411             void* newPtr;
412             const int err = GoldfishAddressSpaceBlock::memoryMap(
413                 cb->getBufferPtr(), cb->mmapedSize,
414                 bufferFd, cb->getMmapedOffset(), &newPtr);
415             if (err) {
416                 native_handle_close(imported);
417                 native_handle_delete(imported);
418                 return FAILURE_V(AIMAPPER_ERROR_NO_RESOURCES, "%s: %s",
419                                  "NO_RESOURCES", strerror(err));
420             }
421             cb->setBufferPtr(newPtr);
422         }
423 
424         if (mDebugLevel >= DebugLevel::IMPORT) {
425             ALOGD("%s:%d: id=%" PRIu64, __func__, __LINE__, getID(*cb));
426         }
427 
428         std::lock_guard<std::mutex> lock(mImportedBuffersMtx);
429         LOG_ALWAYS_FATAL_IF(!mImportedBuffers.insert(cb).second);
430         *outBufferHandle = cb;
431         return AIMAPPER_ERROR_NONE;
432     }
433 
freeBuffer__anon555456480111::GoldfishMapper434     AIMapper_Error freeBuffer(buffer_handle_t buffer) {
435         cb_handle_t* const cb = const_cast<cb_handle_t*>(static_cast<const cb_handle_t*>(buffer));
436 
437         {
438             std::lock_guard<std::mutex> lock(mImportedBuffersMtx);
439             if (mImportedBuffers.erase(cb) == 0) {
440                 return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
441             }
442         }
443 
444         if (mDebugLevel >= DebugLevel::IMPORT) {
445             ALOGD("%s:%d: id=%" PRIu64, __func__, __LINE__, getID(*cb));
446         }
447 
448         if (cb->hostHandle && (cb->lockedUsage & kCPU_WRITE_MASK)) {
449             flushToHost(*cb);
450         }
451         GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(),
452                                                cb->mmapedSize);
453         native_handle_close(cb);
454         native_handle_delete(cb);
455         return AIMAPPER_ERROR_NONE;
456     }
457 
getTransportSize__anon555456480111::GoldfishMapper458     static AIMapper_Error getTransportSize(const buffer_handle_t buffer,
459                                            uint32_t* const outNumFds,
460                                            uint32_t* const outNumInts) {
461         const cb_handle_t* const cb = cb_handle_t::from(buffer);
462         if (!cb) {
463             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
464         }
465 
466         *outNumFds = cb->numFds;
467         *outNumInts = cb->numInts;
468         return AIMAPPER_ERROR_NONE;
469     }
470 
lock__anon555456480111::GoldfishMapper471     AIMapper_Error lock(const buffer_handle_t buffer, const uint64_t uncheckedUsage,
472                         const ARect& accessRegion, const int acquireFence,
473                         void** const outData) const {
474         cb_handle_t* const cb = validateCb(buffer);
475         if (!cb) {
476             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
477         }
478 
479         const CbExternalMetadata& metadata = getExternalMetadata(*cb);
480         if (cb->lockedUsage) {
481             return FAILURE_V(AIMAPPER_ERROR_BAD_BUFFER, "%s: id=%" PRIu64,
482                              "BAD_BUFFER(lockedUsage)", metadata.bufferID);
483         }
484 
485         if ((accessRegion.left < 0) ||
486                 (accessRegion.top < 0) ||
487                 (accessRegion.bottom < accessRegion.top) ||
488                 (accessRegion.right < accessRegion.left) ||
489                 (accessRegion.right > metadata.width) ||
490                 (accessRegion.bottom > metadata.height)) {
491             return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64,
492                              "BAD_VALUE(accessRegion)", metadata.bufferID);
493         }
494         if (accessRegion.right && (accessRegion.left == accessRegion.right)) {
495             return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64,
496                              "BAD_VALUE(accessRegion)", metadata.bufferID);
497         }
498         if (accessRegion.bottom && (accessRegion.top == accessRegion.bottom)) {
499             return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64,
500                              "BAD_VALUE(accessRegion)", metadata.bufferID);
501         }
502 
503         const uint8_t cpuUsage = uncheckedUsage & cb->usage & (kCPU_READ_MASK | kCPU_WRITE_MASK);
504         if (cpuUsage == 0) {
505             return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64,
506                              "BAD_VALUE(uncheckedUsage)", metadata.bufferID);
507         }
508         if ((acquireFence >= 0) && waitFenceFd(acquireFence, __func__)) {
509             return FAILURE_V(AIMAPPER_ERROR_NO_RESOURCES, "%s: id=%" PRIu64,
510                              "NO_RESOURCES(acquireFence)", metadata.bufferID);
511         }
512 
513         if (mDebugLevel >= DebugLevel::LOCK) {
514             ALOGD("%s:%d: id=%" PRIu64 " usage=0x%X accessRegion="
515                   "{ .left=%d, .top=%d, .right=%d, .bottom=%d }",
516                   __func__, __LINE__, metadata.bufferID, cpuUsage, accessRegion.left,
517                   accessRegion.top, accessRegion.right, accessRegion.bottom);
518         }
519 
520         if (cb->hostHandle) {
521             const AIMapper_Error e = readFromHost(*cb);
522             if (e != AIMAPPER_ERROR_NONE) {
523                 return e;
524             }
525         }
526 
527         cb->lockedUsage = cpuUsage;
528         *outData = cb->getBufferPtr();
529         return AIMAPPER_ERROR_NONE;
530     }
531 
unlock__anon555456480111::GoldfishMapper532     AIMapper_Error unlock(const buffer_handle_t buffer, int* const releaseFence) const {
533         cb_handle_t* const cb = validateCb(buffer);
534         if (!cb) {
535             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
536         }
537         if (cb->lockedUsage == 0) {
538             return FAILURE_V(AIMAPPER_ERROR_BAD_BUFFER, "%s: id=%" PRIu64,
539                              "BAD_BUFFER(lockedUsage)", getID(*cb));
540         }
541 
542         if (mDebugLevel >= DebugLevel::LOCK) {
543             ALOGD("%s:%d: id=%" PRIu64, __func__, __LINE__, getID(*cb));
544         }
545 
546         if (cb->hostHandle && (cb->lockedUsage & kCPU_WRITE_MASK)) {
547             flushToHost(*cb);
548         }
549 
550         cb->lockedUsage = 0;
551         *releaseFence = -1;
552         return AIMAPPER_ERROR_NONE;
553     }
554 
flushLockedBuffer__anon555456480111::GoldfishMapper555     AIMapper_Error flushLockedBuffer(const buffer_handle_t buffer) const {
556         const cb_handle_t* const cb = validateCb(buffer);
557         if (!cb) {
558             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
559         }
560         if (mDebugLevel >= DebugLevel::FLUSH) {
561             ALOGD("%s:%d: id=%" PRIu64, __func__, __LINE__, getID(*cb));
562         }
563         if ((cb->lockedUsage & kCPU_WRITE_MASK) == 0) {
564             return FAILURE_V(AIMAPPER_ERROR_BAD_BUFFER, "%s: id=%" PRIu64 ,
565                              "BAD_BUFFER(lockedUsage)", getID(*cb));
566         }
567         if (cb->hostHandle) {
568             flushToHost(*cb);
569         }
570         return AIMAPPER_ERROR_NONE;
571     }
572 
rereadLockedBuffer__anon555456480111::GoldfishMapper573     AIMapper_Error rereadLockedBuffer(const buffer_handle_t buffer) const {
574         const cb_handle_t* const cb = validateCb(buffer);
575         if (!cb) {
576             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
577         }
578         if (mDebugLevel >= DebugLevel::FLUSH) {
579             ALOGD("%s:%d: id=%" PRIu64, __func__, __LINE__, getID(*cb));
580         }
581         if ((cb->lockedUsage & kCPU_READ_MASK) == 0) {
582             return FAILURE_V(AIMAPPER_ERROR_BAD_BUFFER, "%s: id=%" PRIu64 ,
583                              "BAD_BUFFER(lockedUsage)", getID(*cb));
584         }
585 
586         if (cb->hostHandle) {
587             return readFromHost(*cb);
588         } else {
589             return AIMAPPER_ERROR_NONE;
590         }
591     }
592 
readFromHost__anon555456480111::GoldfishMapper593     AIMapper_Error readFromHost(const cb_handle_t& cb) const {
594         const CbExternalMetadata& metadata = getExternalMetadata(cb);
595         const HostConnectionSession conn = getHostConnectionSession();
596         ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
597 
598         const int res = rcEnc->rcColorBufferCacheFlush(
599             rcEnc, cb.hostHandle, 0, true);
600         if (res < 0) {
601             return FAILURE_V(AIMAPPER_ERROR_NO_RESOURCES, "%s: id=%" PRIu64 " res=%d",
602                              "NO_RESOURCES", metadata.bufferID, res);
603         }
604 
605         if (isYuvFormat(getPixelFormat(cb))) {
606             LOG_ALWAYS_FATAL_IF(!rcEnc->hasYUVCache());
607             rcEnc->rcReadColorBufferYUV(rcEnc, cb.hostHandle,
608                                         0, 0, metadata.width, metadata.height,
609                                         cb.getBufferPtr(), cb.bufferSize);
610         } else {
611             LOG_ALWAYS_FATAL_IF(!rcEnc->featureInfo()->hasReadColorBufferDma);
612             rcEnc->bindDmaDirectly(cb.getBufferPtr(),
613                                    getMmapedPhysAddr(cb.getMmapedOffset()));
614             rcEnc->rcReadColorBufferDMA(rcEnc, cb.hostHandle,
615                                         0, 0, metadata.width, metadata.height,
616                                         metadata.glFormat, metadata.glType,
617                                         cb.getBufferPtr(), cb.bufferSize);
618         }
619 
620         return AIMAPPER_ERROR_NONE;
621     }
622 
flushToHost__anon555456480111::GoldfishMapper623     void flushToHost(const cb_handle_t& cb) const {
624         const CbExternalMetadata& metadata = getExternalMetadata(cb);
625         const HostConnectionSession conn = getHostConnectionSession();
626         ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
627 
628         rcEnc->bindDmaDirectly(cb.getBufferPtr(),
629                                getMmapedPhysAddr(cb.getMmapedOffset()));
630         rcEnc->rcUpdateColorBufferDMA(rcEnc, cb.hostHandle,
631                                       0, 0, metadata.width, metadata.height,
632                                       metadata.glFormat, metadata.glType,
633                                       cb.getBufferPtr(), cb.bufferSize);
634     }
635 
getMetadata__anon555456480111::GoldfishMapper636     int32_t getMetadata(const buffer_handle_t buffer,
637                         const AIMapper_MetadataType metadataType,
638                         void* const destBuffer, const size_t destBufferSize) const {
639         if (strcmp(metadataType.name, kStandardMetadataTypeStr)) {
640             return -FAILURE_V(AIMAPPER_ERROR_UNSUPPORTED, "%s: name=%s",
641                               "UNSUPPORTED", metadataType.name);
642         } else {
643             return getStandardMetadata(buffer, metadataType.value,
644                                        destBuffer, destBufferSize);
645         }
646     }
647 
getStandardMetadata__anon555456480111::GoldfishMapper648     int32_t getStandardMetadata(const buffer_handle_t buffer,
649                                 const int64_t standardMetadataType,
650                                 void* const destBuffer,
651                                 const size_t destBufferSize) const {
652         const cb_handle_t* const cb = validateCb(buffer);
653         if (!cb) {
654             return -FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
655         }
656 
657         // don't log dry runs
658         if (destBufferSize && (mDebugLevel >= DebugLevel::METADATA)) {
659             ALOGD("%s:%d: id=%" PRIu64 " standardMetadataType=%" PRId64,
660                   __func__, __LINE__, getID(*cb), standardMetadataType);
661         }
662 
663         return getStandardMetadataImpl(*cb, MetadataWriter(destBuffer, destBufferSize),
664                                        static_cast<StandardMetadataType>(standardMetadataType));
665     }
666 
setMetadata__anon555456480111::GoldfishMapper667     AIMapper_Error setMetadata(const buffer_handle_t buffer,
668                                const AIMapper_MetadataType metadataType,
669                                const void* const metadata, const size_t metadataSize) const {
670         if (strcmp(metadataType.name, kStandardMetadataTypeStr)) {
671             return FAILURE_V(AIMAPPER_ERROR_UNSUPPORTED, "%s: name=%s",
672                              "UNSUPPORTED", metadataType.name);
673         } else {
674             return setStandardMetadata(buffer, metadataType.value,
675                                        metadata, metadataSize);
676         }
677     }
678 
setStandardMetadata__anon555456480111::GoldfishMapper679     AIMapper_Error setStandardMetadata(const buffer_handle_t buffer,
680                                        const int64_t standardMetadataType,
681                                        const void* const metadata,
682                                        const size_t metadataSize) const {
683         const cb_handle_t* const cb = validateCb(buffer);
684         if (!cb) {
685             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
686         }
687 
688         if (mDebugLevel >= DebugLevel::METADATA) {
689             ALOGD("%s:%d: id=%" PRIu64 " standardMetadataType=%" PRId64,
690                   __func__, __LINE__, getID(*cb), standardMetadataType);
691         }
692 
693         return setStandardMetadataImpl(*cb, MetadataReader(metadata, metadataSize),
694                                        static_cast<StandardMetadataType>(standardMetadataType));
695     }
696 
getStandardMetadataImpl__anon555456480111::GoldfishMapper697     int32_t getStandardMetadataImpl(const cb_handle_t& cb, MetadataWriter writer,
698                                     const StandardMetadataType standardMetadataType) const {
699         const auto putMetadataHeader = [](MetadataWriter& writer,
700                                           const StandardMetadataType standardMetadataType) -> MetadataWriter& {
701             return writer.write(kStandardMetadataTypeTag)
702                          .write(static_cast<int64_t>(standardMetadataType));
703         };
704 
705         const CbExternalMetadata& metadata = getExternalMetadata(cb);
706         switch (standardMetadataType) {
707         case StandardMetadataType::BUFFER_ID:
708             putMetadataHeader(writer, standardMetadataType)
709                 .write<uint64_t>(metadata.bufferID);
710             break;
711 
712         case StandardMetadataType::NAME:
713             putMetadataHeader(writer, standardMetadataType)
714                 .write(std::string_view(metadata.name, metadata.nameSize));
715             break;
716 
717         case StandardMetadataType::WIDTH:
718             putMetadataHeader(writer, standardMetadataType)
719                 .write<uint64_t>(metadata.width);
720             break;
721 
722         case StandardMetadataType::HEIGHT:
723             putMetadataHeader(writer, standardMetadataType)
724                 .write<uint64_t>(metadata.height);
725             break;
726 
727         case StandardMetadataType::LAYER_COUNT:
728             putMetadataHeader(writer, standardMetadataType)
729                 .write<uint64_t>(1);
730             break;
731 
732         case StandardMetadataType::PIXEL_FORMAT_REQUESTED:
733             putMetadataHeader(writer, standardMetadataType)
734                 .write<uint32_t>(cb.format);
735             break;
736 
737         case StandardMetadataType::PIXEL_FORMAT_FOURCC:
738             putMetadataHeader(writer, standardMetadataType)
739                 .write<uint32_t>(cb.drmformat);
740             break;
741 
742         case StandardMetadataType::PIXEL_FORMAT_MODIFIER:
743             putMetadataHeader(writer, standardMetadataType)
744                 .write<uint64_t>(DRM_FORMAT_MOD_LINEAR);
745             break;
746 
747         case StandardMetadataType::USAGE:
748             putMetadataHeader(writer, standardMetadataType)
749                 .write<uint64_t>(cb.usage);
750             break;
751 
752         case StandardMetadataType::ALLOCATION_SIZE:
753             putMetadataHeader(writer, standardMetadataType)
754                 .write<uint64_t>(cb.mmapedSize);
755             break;
756 
757         case StandardMetadataType::PROTECTED_CONTENT:
758             putMetadataHeader(writer, standardMetadataType)
759                 .write<uint64_t>((cb.usage & static_cast<uint64_t>(BufferUsage::PROTECTED))
760                                  ? 1 : 0);
761             break;
762 
763         case StandardMetadataType::COMPRESSION:
764             putMetadataHeader(writer, standardMetadataType)
765                 .write(kCompressionTag)
766                 .write(static_cast<int64_t>(aahgc::Compression::NONE));
767             break;
768 
769         case StandardMetadataType::INTERLACED:
770             putMetadataHeader(writer, standardMetadataType)
771                 .write(kInterlacedTag)
772                 .write(static_cast<int64_t>(aahgc::Interlaced::NONE));
773             break;
774 
775         case StandardMetadataType::CHROMA_SITING:
776             putMetadataHeader(writer, standardMetadataType)
777                 .write(kChromaSitingTag)
778                 .write(static_cast<int64_t>(getFormatChromaSiting(getPixelFormat(cb))));
779             break;
780 
781         case StandardMetadataType::PLANE_LAYOUTS: {
782                 const unsigned planeLayoutSize = metadata.planeLayoutSize;
783                 if (!planeLayoutSize) {
784                     return -AIMAPPER_ERROR_UNSUPPORTED;
785                 }
786                 const PlaneLayoutComponent* const layoutComponents =
787                     metadata.planeLayoutComponent;
788 
789                 putMetadataHeader(writer, standardMetadataType)
790                     .write<int64_t>(planeLayoutSize);
791                 for (unsigned plane = 0; plane < planeLayoutSize; ++plane) {
792                     const auto& planeLayout = metadata.planeLayout[plane];
793                     unsigned n = planeLayout.componentsSize;
794                     const PlaneLayoutComponent* component =
795                         layoutComponents + planeLayout.componentsBase;
796 
797                     writer.write<int64_t>(n);
798                     for (; n > 0; --n, ++component) {
799                         writer.write(kPlaneLayoutComponentTypeTag)
800                               .write<int64_t>(component->type)
801                               .write<int64_t>(component->offsetInBits)
802                               .write<int64_t>(component->sizeInBits);
803                     }
804 
805                     const unsigned horizontalSubsampling =
806                         (1U << planeLayout.horizontalSubsamplingShift);
807                     const unsigned verticalSubsampling =
808                         (1U << planeLayout.verticalSubsamplingShift);
809 
810                     writer.write<int64_t>(planeLayout.offsetInBytes)
811                           .write<int64_t>(planeLayout.sampleIncrementInBytes * CHAR_BIT)
812                           .write<int64_t>(planeLayout.strideInBytes)
813                           .write<int64_t>(metadata.width / horizontalSubsampling)
814                           .write<int64_t>(metadata.height / verticalSubsampling)
815                           .write<int64_t>(planeLayout.totalSizeInBytes)
816                           .write<int64_t>(horizontalSubsampling)
817                           .write<int64_t>(verticalSubsampling);
818                 }
819             }
820             break;
821 
822         case StandardMetadataType::CROP: {
823                 unsigned planeLayoutSize = metadata.planeLayoutSize;
824                 if (!planeLayoutSize) {
825                     return -AIMAPPER_ERROR_UNSUPPORTED;
826                 }
827 
828                 putMetadataHeader(writer, standardMetadataType)
829                     .write<uint64_t>(planeLayoutSize);
830                 for (; planeLayoutSize > 0; --planeLayoutSize) {
831                     /*
832                      * b/359690632: `width`,`height` and `CROP` are uint64_t
833                      * in the spec. But the metadata parser in Android uses
834                      * int32_t for `CROP`.
835                      */
836                     writer.write<int32_t>(0).write<int32_t>(0)
837                           .write<int32_t>(metadata.width)
838                           .write<int32_t>(metadata.height);
839                 }
840             }
841             break;
842 
843         case StandardMetadataType::DATASPACE:
844             putMetadataHeader(writer, standardMetadataType)
845                 .write<int32_t>(metadata.dataspace);
846             break;
847 
848         case StandardMetadataType::BLEND_MODE:
849             putMetadataHeader(writer, standardMetadataType)
850                 .write<int32_t>(metadata.blendMode);
851             break;
852 
853         case StandardMetadataType::SMPTE2086:
854             if (metadata.has_smpte2086) {
855                 const auto& smpte2086 = metadata.smpte2086;
856                 putMetadataHeader(writer, standardMetadataType)
857                       .write(smpte2086.primaryRed.x).write(smpte2086.primaryRed.y)
858                       .write(smpte2086.primaryGreen.x).write(smpte2086.primaryGreen.y)
859                       .write(smpte2086.primaryBlue.x).write(smpte2086.primaryBlue.y)
860                       .write(smpte2086.whitePoint.x).write(smpte2086.whitePoint.y)
861                       .write(smpte2086.maxLuminance).write(smpte2086.minLuminance);
862             }
863             break;
864 
865         case StandardMetadataType::CTA861_3:
866             if (metadata.has_cta861_3) {
867                 const auto& cta861_3 = metadata.cta861_3;
868                 putMetadataHeader(writer, standardMetadataType)
869                       .write(cta861_3.maxContentLightLevel)
870                       .write(cta861_3.maxFrameAverageLightLevel);
871             }
872             break;
873 
874         case StandardMetadataType::STRIDE: {
875                 const uint32_t value = (metadata.planeLayoutSize == 1) ?
876                     (metadata.planeLayout[0].strideInBytes /
877                      metadata.planeLayout[0].sampleIncrementInBytes) : 0;
878 
879                 putMetadataHeader(writer, standardMetadataType).write(value);
880             }
881             break;
882 
883         default:
884             return -FAILURE_V(AIMAPPER_ERROR_UNSUPPORTED,
885                               "%s: id=%" PRIu64 ": unexpected standardMetadataType=%" PRId64,
886                               "UNSUPPORTED", metadata.bufferID, static_cast<int64_t>(standardMetadataType));
887         }
888 
889         return writer.desiredSize();
890     }
891 
setStandardMetadataImpl__anon555456480111::GoldfishMapper892     AIMapper_Error setStandardMetadataImpl(const cb_handle_t& cb, MetadataReader reader,
893                                            const StandardMetadataType standardMetadataType) const {
894         const auto checkMetadataHeader = [](MetadataReader& reader,
895                                             const StandardMetadataType standardMetadataType) {
896             if (reader.readString().compare(kStandardMetadataTypeTag)) {
897                 return false;
898             }
899 
900             const std::optional<int64_t> type = reader.readInt<int64_t>();
901             return type.has_value() &&
902                    (type == static_cast<int64_t>(standardMetadataType)) &&
903                    reader.ok();
904         };
905 
906         CbExternalMetadata& metadata = getExternalMetadata(cb);
907         switch (standardMetadataType) {
908         case StandardMetadataType::DATASPACE:
909             if (!checkMetadataHeader(reader, standardMetadataType)) {
910                 return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
911                                  "BAD_VALUE", metadata.bufferID, "DATASPACE");
912             }
913 
914             reader.read(metadata.dataspace);
915             if (!reader.ok()) {
916                 return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
917                                  "BAD_VALUE", metadata.bufferID, "DATASPACE");
918             }
919             break;
920 
921         case StandardMetadataType::BLEND_MODE:
922             if (!checkMetadataHeader(reader, standardMetadataType)) {
923                 return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
924                                  "BAD_VALUE", metadata.bufferID, "BLEND_MODE");
925             }
926             reader.read(metadata.blendMode);
927             if (!reader.ok()) {
928                 return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
929                                  "BAD_VALUE", metadata.bufferID, "BLEND_MODE");
930             }
931             break;
932 
933         case StandardMetadataType::SMPTE2086:
934             if (reader.remaining() > 0) {
935                 if (!checkMetadataHeader(reader, standardMetadataType)) {
936                     return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
937                                      "BAD_VALUE", metadata.bufferID, "SMPTE2086");
938                 }
939 
940                 CbExternalMetadata::Smpte2086 smpte2086;
941                 reader.read(smpte2086.primaryRed.x).read(smpte2086.primaryRed.y)
942                       .read(smpte2086.primaryGreen.x).read(smpte2086.primaryGreen.y)
943                       .read(smpte2086.primaryBlue.x).read(smpte2086.primaryBlue.y)
944                       .read(smpte2086.whitePoint.x).read(smpte2086.whitePoint.y)
945                       .read(smpte2086.maxLuminance).read(smpte2086.minLuminance);
946                 if (reader.ok()) {
947                     metadata.smpte2086 = smpte2086;
948                     metadata.has_smpte2086 = true;
949                 } else {
950                     return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
951                                      "BAD_VALUE", metadata.bufferID, "SMPTE2086");
952                 }
953             } else {
954                 metadata.has_smpte2086 = false;
955             }
956             break;
957 
958         case StandardMetadataType::CTA861_3:
959             if (reader.remaining() > 0) {
960                 if (!checkMetadataHeader(reader, standardMetadataType)) {
961                     return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
962                                      "BAD_VALUE", metadata.bufferID, "CTA861_3");
963                 }
964 
965                 CbExternalMetadata::Cta861_3 cta861_3;
966                 reader.read(cta861_3.maxContentLightLevel)
967                       .read(cta861_3.maxFrameAverageLightLevel);
968                 if (reader.ok()) {
969                     metadata.cta861_3 = cta861_3;
970                     metadata.has_cta861_3 = true;
971                 } else {
972                     return FAILURE_V(AIMAPPER_ERROR_BAD_VALUE, "%s: id=%" PRIu64 ": %s",
973                                      "BAD_VALUE", metadata.bufferID, "CTA861_3");
974                 }
975             } else {
976                 metadata.has_cta861_3 = false;
977             }
978             break;
979 
980         default:
981             return FAILURE_V(AIMAPPER_ERROR_UNSUPPORTED,
982                              "%s: id=%" PRIu64 ": standardMetadataType=%" PRId64,
983                              "UNSUPPORTED", metadata.bufferID, static_cast<int64_t>(standardMetadataType));
984         }
985 
986         return AIMAPPER_ERROR_NONE;
987     }
988 
listSupportedMetadataTypes__anon555456480111::GoldfishMapper989     static AIMapper_Error listSupportedMetadataTypes(
990             const AIMapper_MetadataTypeDescription** outDescriptionList,
991             size_t* outNumberOfDescriptions) {
992         *outDescriptionList = kMetadataTypeDescriptionList;
993         *outNumberOfDescriptions = arraySize(kMetadataTypeDescriptionList);
994         return AIMAPPER_ERROR_NONE;
995     }
996 
dumpBuffer__anon555456480111::GoldfishMapper997     AIMapper_Error dumpBuffer(const buffer_handle_t buffer,
998                               const AIMapper_DumpBufferCallback dumpBufferCallback,
999                               void* const context) const {
1000         const cb_handle_t* const cb = validateCb(buffer);
1001         if (!cb) {
1002             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
1003         }
1004 
1005         if (mDebugLevel >= DebugLevel::METADATA) {
1006             ALOGD("%s:%d: id=%" PRIu64, __func__, __LINE__, getID(*cb));
1007         }
1008 
1009         std::vector<uint8_t> metadataBuffer(kMetadataBufferInitialSize);
1010         dumpBufferImpl(*cb, dumpBufferCallback, context, metadataBuffer);
1011         return AIMAPPER_ERROR_NONE;
1012     }
1013 
dumpBufferImpl__anon555456480111::GoldfishMapper1014     void dumpBufferImpl(const cb_handle_t& cb,
1015                         const AIMapper_DumpBufferCallback dumpBufferCallback,
1016                         void* const context,
1017                         std::vector<uint8_t>& metadataBuffer) const {
1018         for (const auto& m : kMetadataTypeDescriptionList) {
1019             if (m.isGettable) {
1020                 bool firstTry = true;
1021 retryWithLargerBuffer:
1022                 MetadataWriter writer(metadataBuffer.data(), metadataBuffer.size());
1023                 const int32_t desiredSize = getStandardMetadataImpl(cb, writer,
1024                     static_cast<StandardMetadataType>(m.metadataType.value));
1025                 if (desiredSize < 0) {
1026                     // should not happen, update `getStandardMetadata`
1027                     continue;
1028                 } else if (desiredSize <= metadataBuffer.size()) {
1029                     (*dumpBufferCallback)(context, m.metadataType,
1030                                           metadataBuffer.data(), desiredSize);
1031                 } else {
1032                     LOG_ALWAYS_FATAL_IF(!firstTry);
1033                     metadataBuffer.resize(desiredSize);
1034                     firstTry = false;
1035                     goto retryWithLargerBuffer;
1036                 }
1037             }
1038         }
1039     }
1040 
dumpAllBuffers__anon555456480111::GoldfishMapper1041     AIMapper_Error dumpAllBuffers(const AIMapper_BeginDumpBufferCallback beginDumpCallback,
1042                                   const AIMapper_DumpBufferCallback dumpBufferCallback,
1043                                   void* const context) const {
1044         std::vector<uint8_t> metadataBuffer(kMetadataBufferInitialSize);
1045 
1046         std::lock_guard<std::mutex> lock(mImportedBuffersMtx);
1047         for (const cb_handle_t* const cb : mImportedBuffers) {
1048             (*beginDumpCallback)(context);
1049             dumpBufferImpl(*cb, dumpBufferCallback, context, metadataBuffer);
1050         }
1051 
1052         return AIMAPPER_ERROR_NONE;
1053     }
1054 
getReservedRegion__anon555456480111::GoldfishMapper1055     AIMapper_Error getReservedRegion(const buffer_handle_t buffer,
1056                                      void** const outReservedRegion,
1057                                      uint64_t* const outReservedSize) const {
1058         const cb_handle_t* const cb = validateCb(buffer);
1059         if (!cb) {
1060             return FAILURE(AIMAPPER_ERROR_BAD_BUFFER);
1061         }
1062 
1063         CbExternalMetadata& metadata = getExternalMetadata(*cb);
1064         const size_t reservedRegionSize = metadata.reservedRegionSize;
1065         if (reservedRegionSize) {
1066             *outReservedRegion = &metadata + 1;  // right after `CbExternalMetadata`
1067         } else {
1068             *outReservedRegion = nullptr;
1069         }
1070         *outReservedSize = reservedRegionSize;
1071         return AIMAPPER_ERROR_NONE;
1072     }
1073 
validateCb__anon555456480111::GoldfishMapper1074     cb_handle_t* validateCb(const buffer_handle_t buffer) const {
1075         cb_handle_t* cb = const_cast<cb_handle_t*>(static_cast<const cb_handle_t*>(buffer));
1076         std::lock_guard<std::mutex> lock(mImportedBuffersMtx);
1077         return mImportedBuffers.count(cb) ? cb : nullptr;
1078     }
1079 
getHostConnectionSession__anon555456480111::GoldfishMapper1080     HostConnectionSession getHostConnectionSession() const {
1081         return HostConnectionSession(mHostConn.get());
1082     }
1083 
getMmapedPhysAddr__anon555456480111::GoldfishMapper1084     uint64_t getMmapedPhysAddr(const uint64_t offset) const {
1085         return mPhysAddrToOffset + offset;
1086     }
1087 
1088     AIMapper mMapper;
1089     const std::unique_ptr<HostConnection> mHostConn;
1090     std::unordered_set<const cb_handle_t*> mImportedBuffers;
1091     uint64_t mPhysAddrToOffset;
1092     mutable std::mutex mImportedBuffersMtx;
1093     const DebugLevel mDebugLevel;
1094 };
1095 }  // namespace
1096 
1097 extern "C" uint32_t ANDROID_HAL_MAPPER_VERSION = AIMAPPER_VERSION_5;
1098 
AIMapper_loadIMapper(AIMapper * _Nullable * _Nonnull outImplementation)1099 extern "C" AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) {
1100     static GoldfishMapper instance;
1101     *outImplementation = &instance.getAIMapper();
1102     return AIMAPPER_ERROR_NONE;
1103 }
1104