1 /* 2 * Copyright (C) 2022 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 #pragma once 18 19 #include <android-base/unique_fd.h> 20 #include <android/hardware/graphics/mapper/IMapper.h> 21 #include <log/log.h> 22 23 #include <mutex> 24 #include <optional> 25 #include <type_traits> 26 27 /** 28 * Helper utilities for providing an IMapper-StableC implementation. 29 */ 30 31 namespace vendor::mapper { 32 33 /** 34 * Extend from this interface to provide Version 5 of the IMapper interface 35 */ 36 struct IMapperV5Impl { 37 static const auto version = AIMAPPER_VERSION_5; 38 virtual ~IMapperV5Impl() = default; 39 40 virtual AIMapper_Error importBuffer(const native_handle_t* _Nonnull handle, 41 buffer_handle_t _Nullable* _Nonnull outBufferHandle) = 0; 42 43 virtual AIMapper_Error freeBuffer(buffer_handle_t _Nonnull buffer) = 0; 44 45 virtual AIMapper_Error getTransportSize(buffer_handle_t _Nonnull buffer, 46 uint32_t* _Nonnull outNumFds, 47 uint32_t* _Nonnull outNumInts) = 0; 48 49 virtual AIMapper_Error lock(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage, 50 ARect accessRegion, int acquireFence, 51 void* _Nullable* _Nonnull outData) = 0; 52 53 virtual AIMapper_Error unlock(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) = 0; 54 55 virtual AIMapper_Error flushLockedBuffer(buffer_handle_t _Nonnull buffer) = 0; 56 57 virtual AIMapper_Error rereadLockedBuffer(buffer_handle_t _Nonnull buffer) = 0; 58 59 virtual int32_t getMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType, 60 void* _Nullable destBuffer, size_t destBufferSize) = 0; 61 62 virtual int32_t getStandardMetadata(buffer_handle_t _Nonnull buffer, 63 int64_t standardMetadataType, void* _Nullable destBuffer, 64 size_t destBufferSize) = 0; 65 66 virtual AIMapper_Error setMetadata(buffer_handle_t _Nonnull buffer, 67 AIMapper_MetadataType metadataType, 68 const void* _Nonnull metadata, size_t metadataSize) = 0; 69 70 virtual AIMapper_Error setStandardMetadata(buffer_handle_t _Nonnull buffer, 71 int64_t standardMetadataType, 72 const void* _Nonnull metadata, 73 size_t metadataSize) = 0; 74 75 virtual AIMapper_Error listSupportedMetadataTypes( 76 const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList, 77 size_t* _Nonnull outNumberOfDescriptions) = 0; 78 79 virtual AIMapper_Error dumpBuffer(buffer_handle_t _Nonnull bufferHandle, 80 AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, 81 void* _Null_unspecified context) = 0; 82 83 virtual AIMapper_Error dumpAllBuffers( 84 AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback, 85 AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, 86 void* _Null_unspecified context) = 0; 87 88 virtual AIMapper_Error getReservedRegion(buffer_handle_t _Nonnull buffer, 89 void* _Nullable* _Nonnull outReservedRegion, 90 uint64_t* _Nonnull outReservedSize) = 0; 91 }; 92 93 namespace provider { 94 #ifndef __cpp_inline_variables 95 #error "Only C++17 & newer is supported; inline variables is missing" 96 #endif 97 98 inline void* _Nullable sIMapperInstance = nullptr; 99 } // namespace provider 100 101 template <typename IMPL> 102 class IMapperProvider { 103 private: 104 static_assert(IMPL::version >= AIMAPPER_VERSION_5, "Must be at least AIMAPPER_VERSION_5"); 105 static_assert(std::is_final_v<IMPL>, "Implementation must be final"); 106 static_assert(std::is_constructible_v<IMPL>, "Implementation must have a no-args constructor"); 107 108 std::once_flag mLoadOnceFlag; 109 std::optional<IMPL> mImpl; 110 AIMapper mMapper = {}; 111 impl()112 static IMPL& impl() { 113 return *reinterpret_cast<IMapperProvider<IMPL>*>(provider::sIMapperInstance)->mImpl; 114 } 115 bindV5()116 void bindV5() { 117 mMapper.v5 = { 118 .importBuffer = [](const native_handle_t* _Nonnull handle, 119 buffer_handle_t _Nullable* _Nonnull outBufferHandle) 120 -> AIMapper_Error { return impl().importBuffer(handle, outBufferHandle); }, 121 122 .freeBuffer = [](buffer_handle_t _Nonnull buffer) -> AIMapper_Error { 123 return impl().freeBuffer(buffer); 124 }, 125 126 .getTransportSize = [](buffer_handle_t _Nonnull buffer, 127 uint32_t* _Nonnull outNumFds, 128 uint32_t* _Nonnull outNumInts) -> AIMapper_Error { 129 return impl().getTransportSize(buffer, outNumFds, outNumInts); 130 }, 131 132 .lock = [](buffer_handle_t _Nonnull buffer, uint64_t cpuUsage, ARect accessRegion, 133 int acquireFence, void* _Nullable* _Nonnull outData) -> AIMapper_Error { 134 return impl().lock(buffer, cpuUsage, accessRegion, acquireFence, outData); 135 }, 136 137 .unlock = [](buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) 138 -> AIMapper_Error { return impl().unlock(buffer, releaseFence); }, 139 140 .flushLockedBuffer = [](buffer_handle_t _Nonnull buffer) -> AIMapper_Error { 141 return impl().flushLockedBuffer(buffer); 142 }, 143 144 .rereadLockedBuffer = [](buffer_handle_t _Nonnull buffer) -> AIMapper_Error { 145 return impl().rereadLockedBuffer(buffer); 146 }, 147 148 .getMetadata = [](buffer_handle_t _Nonnull buffer, 149 AIMapper_MetadataType metadataType, void* _Nullable destBuffer, 150 size_t destBufferSize) -> int32_t { 151 return impl().getMetadata(buffer, metadataType, destBuffer, destBufferSize); 152 }, 153 154 .getStandardMetadata = [](buffer_handle_t _Nonnull buffer, 155 int64_t standardMetadataType, void* _Nullable destBuffer, 156 size_t destBufferSize) -> int32_t { 157 return impl().getStandardMetadata(buffer, standardMetadataType, destBuffer, 158 destBufferSize); 159 }, 160 161 .setMetadata = [](buffer_handle_t _Nonnull buffer, 162 AIMapper_MetadataType metadataType, const void* _Nonnull metadata, 163 size_t metadataSize) -> AIMapper_Error { 164 return impl().setMetadata(buffer, metadataType, metadata, metadataSize); 165 }, 166 167 .setStandardMetadata = 168 [](buffer_handle_t _Nonnull buffer, int64_t standardMetadataType, 169 const void* _Nonnull metadata, size_t metadataSize) -> AIMapper_Error { 170 return impl().setStandardMetadata(buffer, standardMetadataType, metadata, 171 metadataSize); 172 }, 173 174 .listSupportedMetadataTypes = 175 [](const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList, 176 size_t* _Nonnull outNumberOfDescriptions) -> AIMapper_Error { 177 return impl().listSupportedMetadataTypes(outDescriptionList, 178 outNumberOfDescriptions); 179 }, 180 181 .dumpBuffer = [](buffer_handle_t _Nonnull bufferHandle, 182 AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, 183 void* _Null_unspecified context) -> AIMapper_Error { 184 return impl().dumpBuffer(bufferHandle, dumpBufferCallback, context); 185 }, 186 187 .dumpAllBuffers = 188 [](AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback, 189 AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, 190 void* _Null_unspecified context) { 191 return impl().dumpAllBuffers(beginDumpBufferCallback, 192 dumpBufferCallback, context); 193 }, 194 195 .getReservedRegion = [](buffer_handle_t _Nonnull buffer, 196 void* _Nullable* _Nonnull outReservedRegion, 197 uint64_t* _Nonnull outReservedSize) -> AIMapper_Error { 198 return impl().getReservedRegion(buffer, outReservedRegion, outReservedSize); 199 }, 200 }; 201 } 202 203 public: 204 explicit IMapperProvider() = default; 205 load(AIMapper * _Nullable * _Nonnull outImplementation)206 AIMapper_Error load(AIMapper* _Nullable* _Nonnull outImplementation) { 207 std::call_once(mLoadOnceFlag, [this] { 208 LOG_ALWAYS_FATAL_IF(provider::sIMapperInstance != nullptr, 209 "AIMapper implementation already loaded!"); 210 provider::sIMapperInstance = this; 211 mImpl.emplace(); 212 mMapper.version = IMPL::version; 213 if (IMPL::version >= AIMAPPER_VERSION_5) { 214 bindV5(); 215 } 216 }); 217 *outImplementation = &mMapper; 218 return AIMAPPER_ERROR_NONE; 219 } 220 }; 221 222 } // namespace vendor::mapper 223