• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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