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 <aidl/android/hardware/graphics/common/BlendMode.h>
20 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
21 #include <aidl/android/hardware/graphics/common/Cta861_3.h>
22 #include <aidl/android/hardware/graphics/common/Dataspace.h>
23 #include <aidl/android/hardware/graphics/common/ExtendableType.h>
24 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
25 #include <aidl/android/hardware/graphics/common/PlaneLayout.h>
26 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
27 #include <aidl/android/hardware/graphics/common/Rect.h>
28 #include <aidl/android/hardware/graphics/common/Smpte2086.h>
29 #include <aidl/android/hardware/graphics/common/StandardMetadataType.h>
30 #include <aidl/android/hardware/graphics/common/XyColor.h>
31 #include <android/hardware/graphics/mapper/IMapper.h>
32 
33 #include <cinttypes>
34 #include <string_view>
35 #include <type_traits>
36 #include <vector>
37 
38 namespace android::hardware::graphics::mapper {
39 
40 using ::aidl::android::hardware::graphics::common::BlendMode;
41 using ::aidl::android::hardware::graphics::common::BufferUsage;
42 using ::aidl::android::hardware::graphics::common::Cta861_3;
43 using ::aidl::android::hardware::graphics::common::Dataspace;
44 using ::aidl::android::hardware::graphics::common::ExtendableType;
45 using ::aidl::android::hardware::graphics::common::PixelFormat;
46 using ::aidl::android::hardware::graphics::common::PlaneLayout;
47 using ::aidl::android::hardware::graphics::common::PlaneLayoutComponent;
48 using ::aidl::android::hardware::graphics::common::Rect;
49 using ::aidl::android::hardware::graphics::common::Smpte2086;
50 using ::aidl::android::hardware::graphics::common::StandardMetadataType;
51 using ::aidl::android::hardware::graphics::common::XyColor;
52 
53 class MetadataWriter {
54   private:
55     uint8_t* _Nonnull mDest;
56     size_t mSizeRemaining = 0;
57     int32_t mDesiredSize = 0;
58 
reserve(size_t sizeToWrite)59     void* _Nullable reserve(size_t sizeToWrite) {
60         if (mDesiredSize < 0) {
61             // Error state
62             return nullptr;
63         }
64         if (__builtin_add_overflow(mDesiredSize, sizeToWrite, &mDesiredSize)) {
65             // Overflowed, abort writing any further data
66             mDesiredSize = -AIMAPPER_ERROR_BAD_VALUE;
67             mSizeRemaining = 0;
68             return nullptr;
69         }
70         if (sizeToWrite > mSizeRemaining) {
71             mSizeRemaining = 0;
72             return nullptr;
73         } else {
74             mSizeRemaining -= sizeToWrite;
75             uint8_t* whereToWrite = mDest;
76             mDest += sizeToWrite;
77             return whereToWrite;
78         }
79     }
80 
81   public:
MetadataWriter(void * _Nullable destBuffer,size_t destBufferSize)82     explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize)
83         : mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {}
84 
desiredSize()85     [[nodiscard]] int32_t desiredSize() const { return mDesiredSize; }
86 
87     template <typename HEADER>
writeHeader()88     MetadataWriter& writeHeader() {
89         return write(HEADER::name).template write<int64_t>(HEADER::value);
90     }
91 
92     template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
write(T value)93     MetadataWriter& write(T value) {
94         auto sizeToWrite = sizeof(T);
95         if (void* dest = reserve(sizeToWrite)) {
96             memcpy(dest, &value, sizeToWrite);
97         }
98         return *this;
99     }
100 
write(float value)101     MetadataWriter& write(float value) {
102         auto sizeToWrite = sizeof(float);
103         if (void* dest = reserve(sizeToWrite)) {
104             memcpy(dest, &value, sizeToWrite);
105         }
106         return *this;
107     }
108 
write(const std::string_view & value)109     MetadataWriter& write(const std::string_view& value) {
110         auto sizeToWrite = value.length();
111         write<int64_t>(sizeToWrite);
112         if (void* dest = reserve(sizeToWrite)) {
113             memcpy(dest, value.data(), sizeToWrite);
114         }
115         return *this;
116     }
117 
write(const std::vector<uint8_t> & value)118     MetadataWriter& write(const std::vector<uint8_t>& value) {
119         auto sizeToWrite = value.size();
120         write<int64_t>(sizeToWrite);
121         if (void* dest = reserve(sizeToWrite)) {
122             memcpy(dest, value.data(), sizeToWrite);
123         }
124         return *this;
125     }
126 
write(const ExtendableType & value)127     MetadataWriter& write(const ExtendableType& value) {
128         return write(value.name).write(value.value);
129     }
130 
write(const XyColor & value)131     MetadataWriter& write(const XyColor& value) { return write(value.x).write(value.y); }
132 };
133 
134 class MetadataReader {
135   private:
136     const uint8_t* _Nonnull mSrc;
137     size_t mSizeRemaining = 0;
138     bool mOk = true;
139 
advance(size_t size)140     const void* _Nullable advance(size_t size) {
141         if (mOk && mSizeRemaining >= size) {
142             const void* buf = mSrc;
143             mSrc += size;
144             mSizeRemaining -= size;
145             return buf;
146         }
147         mOk = false;
148         return nullptr;
149     }
150 
151   public:
MetadataReader(const void * _Nonnull metadata,size_t metadataSize)152     explicit MetadataReader(const void* _Nonnull metadata, size_t metadataSize)
153         : mSrc(reinterpret_cast<const uint8_t*>(metadata)), mSizeRemaining(metadataSize) {}
154 
remaining()155     [[nodiscard]] size_t remaining() const { return mSizeRemaining; }
ok()156     [[nodiscard]] bool ok() const { return mOk; }
157 
158     template <typename HEADER>
checkHeader()159     MetadataReader& checkHeader() {
160         if (HEADER::name != readString()) {
161             mOk = false;
162         }
163         auto value = readInt<int64_t>();
164         if (!value || *value != HEADER::value) {
165             mOk = false;
166         }
167         return *this;
168     }
169 
170     template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
read(T & dest)171     MetadataReader& read(T& dest) {
172         if (const void* src = advance(sizeof(T))) {
173             memcpy(&dest, src, sizeof(T));
174         }
175         return *this;
176     }
177 
read(float & dest)178     MetadataReader& read(float& dest) {
179         if (const void* src = advance(sizeof(float))) {
180             memcpy(&dest, src, sizeof(float));
181         }
182         return *this;
183     }
184 
read(std::string & dest)185     MetadataReader& read(std::string& dest) {
186         dest = readString();
187         return *this;
188     }
189 
read(ExtendableType & dest)190     MetadataReader& read(ExtendableType& dest) {
191         dest.name = readString();
192         read(dest.value);
193         return *this;
194     }
195 
read(XyColor & dest)196     MetadataReader& read(XyColor& dest) {
197         read(dest.x);
198         read(dest.y);
199         return *this;
200     }
201 
202     template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
readInt()203     [[nodiscard]] std::optional<T> readInt() {
204         auto sizeToRead = sizeof(T);
205         if (const void* src = advance(sizeof(T))) {
206             T ret;
207             memcpy(&ret, src, sizeToRead);
208             return ret;
209         }
210         return std::nullopt;
211     }
212 
readString()213     [[nodiscard]] std::string_view readString() {
214         auto lengthOpt = readInt<int64_t>();
215         if (!lengthOpt) {
216             return std::string_view{};
217         }
218         size_t length = lengthOpt.value();
219         if (const void* src = advance(length)) {
220             return std::string_view{reinterpret_cast<const char*>(src), length};
221         }
222         return std::string_view{};
223     }
224 
readExtendable()225     [[nodiscard]] std::optional<ExtendableType> readExtendable() {
226         ExtendableType ret;
227         ret.name = readString();
228         auto value = readInt<int64_t>();
229         if (value) {
230             ret.value = value.value();
231             return ret;
232         } else {
233             return std::nullopt;
234         }
235     }
236 
readBuffer()237     [[nodiscard]] std::vector<uint8_t> readBuffer() {
238         std::vector<uint8_t> ret;
239         size_t length = readInt<int64_t>().value_or(0);
240         if (const void* src = advance(length)) {
241             ret.resize(length);
242             memcpy(ret.data(), src, length);
243         }
244         return ret;
245     }
246 };
247 
248 template <typename HEADER, typename T, class Enable = void>
249 struct MetadataValue {};
250 
251 template <typename HEADER, typename T>
252 struct MetadataValue<HEADER, T, std::enable_if_t<std::is_integral_v<T>>> {
253     [[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
254                                         size_t destBufferSize) {
255         return MetadataWriter{destBuffer, destBufferSize}
256                 .template writeHeader<HEADER>()
257                 .write(value)
258                 .desiredSize();
259     }
260 
261     [[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
262                                                  size_t metadataSize) {
263         return MetadataReader{metadata, metadataSize}
264                 .template checkHeader<HEADER>()
265                 .template readInt<T>();
266     }
267 };
268 
269 template <typename HEADER, typename T>
270 struct MetadataValue<HEADER, T, std::enable_if_t<std::is_enum_v<T>>> {
271     [[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
272                                         size_t destBufferSize) {
273         return MetadataWriter{destBuffer, destBufferSize}
274                 .template writeHeader<HEADER>()
275                 .write(static_cast<std::underlying_type_t<T>>(value))
276                 .desiredSize();
277     }
278 
279     [[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
280                                                  size_t metadataSize) {
281         std::underlying_type_t<T> temp;
282         return MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>().read(temp).ok()
283                        ? std::optional<T>(static_cast<T>(temp))
284                        : std::nullopt;
285     }
286 };
287 
288 template <typename HEADER>
289 struct MetadataValue<HEADER, std::string> {
290     [[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer,
291                                         size_t destBufferSize) {
292         return MetadataWriter{destBuffer, destBufferSize}
293                 .template writeHeader<HEADER>()
294                 .write(value)
295                 .desiredSize();
296     }
297 
298     [[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata,
299                                                            size_t metadataSize) {
300         auto reader = MetadataReader{metadata, metadataSize}.template checkHeader<HEADER>();
301         auto result = reader.readString();
302         return reader.ok() ? std::optional<std::string>{result} : std::nullopt;
303     }
304 };
305 
306 template <typename HEADER>
307 struct MetadataValue<HEADER, ExtendableType> {
308     static_assert(sizeof(int64_t) == sizeof(ExtendableType::value));
309 
310     [[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer,
311                                         size_t destBufferSize) {
312         return MetadataWriter{destBuffer, destBufferSize}
313                 .template writeHeader<HEADER>()
314                 .write(value)
315                 .desiredSize();
316     }
317 
318     [[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata,
319                                                               size_t metadataSize) {
320         return MetadataReader{metadata, metadataSize}
321                 .template checkHeader<HEADER>()
322                 .readExtendable();
323     }
324 };
325 
326 template <typename HEADER>
327 struct MetadataValue<HEADER, std::vector<PlaneLayout>> {
328     [[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values,
329                                         void* _Nullable destBuffer, size_t destBufferSize) {
330         MetadataWriter writer{destBuffer, destBufferSize};
331         writer.template writeHeader<HEADER>();
332         writer.write<int64_t>(values.size());
333         for (const auto& value : values) {
334             writer.write<int64_t>(value.components.size());
335             for (const auto& component : value.components) {
336                 writer.write(component.type)
337                         .write<int64_t>(component.offsetInBits)
338                         .write<int64_t>(component.sizeInBits);
339             }
340             writer.write<int64_t>(value.offsetInBytes)
341                     .write<int64_t>(value.sampleIncrementInBits)
342                     .write<int64_t>(value.strideInBytes)
343                     .write<int64_t>(value.widthInSamples)
344                     .write<int64_t>(value.heightInSamples)
345                     .write<int64_t>(value.totalSizeInBytes)
346                     .write<int64_t>(value.horizontalSubsampling)
347                     .write<int64_t>(value.verticalSubsampling);
348         }
349         return writer.desiredSize();
350     }
351 
352     using DecodeResult = std::optional<std::vector<PlaneLayout>>;
353     [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
354         std::vector<PlaneLayout> values;
355         MetadataReader reader{metadata, metadataSize};
356         reader.template checkHeader<HEADER>();
357         auto numPlanes = reader.readInt<int64_t>().value_or(0);
358         values.reserve(numPlanes);
359         for (int i = 0; i < numPlanes && reader.ok(); i++) {
360             PlaneLayout& value = values.emplace_back();
361             auto numPlaneComponents = reader.readInt<int64_t>().value_or(0);
362             value.components.reserve(numPlaneComponents);
363             for (int j = 0; j < numPlaneComponents && reader.ok(); j++) {
364                 PlaneLayoutComponent& component = value.components.emplace_back();
365                 reader.read(component.type)
366                         .read<int64_t>(component.offsetInBits)
367                         .read<int64_t>(component.sizeInBits);
368             }
369             reader.read<int64_t>(value.offsetInBytes)
370                     .read<int64_t>(value.sampleIncrementInBits)
371                     .read<int64_t>(value.strideInBytes)
372                     .read<int64_t>(value.widthInSamples)
373                     .read<int64_t>(value.heightInSamples)
374                     .read<int64_t>(value.totalSizeInBytes)
375                     .read<int64_t>(value.horizontalSubsampling)
376                     .read<int64_t>(value.verticalSubsampling);
377         }
378         return reader.ok() ? DecodeResult{std::move(values)} : std::nullopt;
379     }
380 };
381 
382 template <typename HEADER>
383 struct MetadataValue<HEADER, std::vector<Rect>> {
384     [[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer,
385                                         size_t destBufferSize) {
386         MetadataWriter writer{destBuffer, destBufferSize};
387         writer.template writeHeader<HEADER>();
388         writer.write<int64_t>(value.size());
389         for (auto& rect : value) {
390             writer.write<int32_t>(rect.left)
391                     .write<int32_t>(rect.top)
392                     .write<int32_t>(rect.right)
393                     .write<int32_t>(rect.bottom);
394         }
395         return writer.desiredSize();
396     }
397 
398     using DecodeResult = std::optional<std::vector<Rect>>;
399     [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
400         MetadataReader reader{metadata, metadataSize};
401         reader.template checkHeader<HEADER>();
402         std::vector<Rect> value;
403         auto numRects = reader.readInt<int64_t>().value_or(0);
404         value.reserve(numRects);
405         for (int i = 0; i < numRects && reader.ok(); i++) {
406             Rect& rect = value.emplace_back();
407             reader.read<int32_t>(rect.left)
408                     .read<int32_t>(rect.top)
409                     .read<int32_t>(rect.right)
410                     .read<int32_t>(rect.bottom);
411         }
412         return reader.ok() ? DecodeResult{std::move(value)} : std::nullopt;
413     }
414 };
415 
416 template <typename HEADER>
417 struct MetadataValue<HEADER, std::optional<Smpte2086>> {
418     [[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue,
419                                         void* _Nullable destBuffer, size_t destBufferSize) {
420         if (optValue.has_value()) {
421             const auto& value = *optValue;
422             return MetadataWriter{destBuffer, destBufferSize}
423                     .template writeHeader<HEADER>()
424                     .write(value.primaryRed)
425                     .write(value.primaryGreen)
426                     .write(value.primaryBlue)
427                     .write(value.whitePoint)
428                     .write(value.maxLuminance)
429                     .write(value.minLuminance)
430                     .desiredSize();
431         } else {
432             return 0;
433         }
434     }
435 
436     // Double optional because the value type itself is an optional<>
437     using DecodeResult = std::optional<std::optional<Smpte2086>>;
438     [[nodiscard]] static DecodeResult decode(const void* _Nullable metadata, size_t metadataSize) {
439         std::optional<Smpte2086> optValue{std::nullopt};
440         if (metadataSize > 0) {
441             Smpte2086 value;
442             MetadataReader reader{metadata, metadataSize};
443             reader.template checkHeader<HEADER>();
444             reader.read(value.primaryRed)
445                     .read(value.primaryGreen)
446                     .read(value.primaryBlue)
447                     .read(value.whitePoint)
448                     .read(value.maxLuminance)
449                     .read(value.minLuminance);
450             if (reader.ok()) {
451                 optValue = std::move(value);
452             } else {
453                 return std::nullopt;
454             }
455         }
456         return DecodeResult{std::move(optValue)};
457     }
458 };
459 
460 template <typename HEADER>
461 struct MetadataValue<HEADER, std::optional<Cta861_3>> {
462     [[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue,
463                                         void* _Nullable destBuffer, size_t destBufferSize) {
464         if (optValue.has_value()) {
465             const auto& value = *optValue;
466             return MetadataWriter{destBuffer, destBufferSize}
467                     .template writeHeader<HEADER>()
468                     .write(value.maxContentLightLevel)
469                     .write(value.maxFrameAverageLightLevel)
470                     .desiredSize();
471         } else {
472             return 0;
473         }
474     }
475 
476     // Double optional because the value type itself is an optional<>
477     using DecodeResult = std::optional<std::optional<Cta861_3>>;
478     [[nodiscard]] static DecodeResult decode(const void* _Nullable metadata, size_t metadataSize) {
479         std::optional<Cta861_3> optValue{std::nullopt};
480         if (metadataSize > 0) {
481             MetadataReader reader{metadata, metadataSize};
482             reader.template checkHeader<HEADER>();
483             Cta861_3 value;
484             reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel);
485             if (reader.ok()) {
486                 optValue = std::move(value);
487             } else {
488                 return std::nullopt;
489             }
490         }
491         return DecodeResult{std::move(optValue)};
492     }
493 };
494 
495 template <typename HEADER>
496 struct MetadataValue<HEADER, std::optional<std::vector<uint8_t>>> {
497     [[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value,
498                                         void* _Nullable destBuffer, size_t destBufferSize) {
499         if (!value.has_value()) {
500             return 0;
501         }
502         return MetadataWriter{destBuffer, destBufferSize}
503                 .template writeHeader<HEADER>()
504                 .write(*value)
505                 .desiredSize();
506     }
507 
508     using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>;
509     [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
510         std::optional<std::vector<uint8_t>> optValue;
511         if (metadataSize > 0) {
512             MetadataReader reader{metadata, metadataSize};
513             reader.template checkHeader<HEADER>();
514             auto value = reader.readBuffer();
515             if (reader.ok()) {
516                 optValue = std::move(value);
517             } else {
518                 return std::nullopt;
519             }
520         }
521         return DecodeResult{std::move(optValue)};
522     }
523 };
524 
525 template <StandardMetadataType>
526 struct StandardMetadata {};
527 
528 #define DEFINE_TYPE(typeName, typeArg)                                                            \
529     template <>                                                                                   \
530     struct StandardMetadata<StandardMetadataType::typeName> {                                     \
531         using value_type = typeArg;                                                               \
532         struct Header {                                                                           \
533             static constexpr auto name = "android.hardware.graphics.common.StandardMetadataType"; \
534             static constexpr auto value = static_cast<int64_t>(StandardMetadataType::typeName);   \
535         };                                                                                        \
536         using value = MetadataValue<Header, value_type>;                                          \
537         static_assert(                                                                            \
538                 StandardMetadataType::typeName ==                                                 \
539                         ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>(     \
540                                 StandardMetadataType::typeName)],                                 \
541                 "StandardMetadataType must have equivalent value to index");                      \
542     }
543 
544 DEFINE_TYPE(BUFFER_ID, uint64_t);
545 DEFINE_TYPE(NAME, std::string);
546 DEFINE_TYPE(WIDTH, uint64_t);
547 DEFINE_TYPE(HEIGHT, uint64_t);
548 DEFINE_TYPE(LAYER_COUNT, uint64_t);
549 DEFINE_TYPE(PIXEL_FORMAT_REQUESTED, PixelFormat);
550 DEFINE_TYPE(PIXEL_FORMAT_FOURCC, uint32_t);
551 DEFINE_TYPE(PIXEL_FORMAT_MODIFIER, uint64_t);
552 DEFINE_TYPE(USAGE, BufferUsage);
553 DEFINE_TYPE(ALLOCATION_SIZE, uint64_t);
554 DEFINE_TYPE(PROTECTED_CONTENT, uint64_t);
555 DEFINE_TYPE(COMPRESSION, ExtendableType);
556 DEFINE_TYPE(INTERLACED, ExtendableType);
557 DEFINE_TYPE(CHROMA_SITING, ExtendableType);
558 DEFINE_TYPE(PLANE_LAYOUTS, std::vector<PlaneLayout>);
559 DEFINE_TYPE(CROP, std::vector<Rect>);
560 DEFINE_TYPE(DATASPACE, Dataspace);
561 DEFINE_TYPE(BLEND_MODE, BlendMode);
562 DEFINE_TYPE(SMPTE2086, std::optional<Smpte2086>);
563 DEFINE_TYPE(CTA861_3, std::optional<Cta861_3>);
564 DEFINE_TYPE(SMPTE2094_10, std::optional<std::vector<uint8_t>>);
565 DEFINE_TYPE(SMPTE2094_40, std::optional<std::vector<uint8_t>>);
566 DEFINE_TYPE(STRIDE, uint32_t);
567 
568 #undef DEFINE_TYPE
569 
570 #if defined(__cplusplus) && __cplusplus >= 202002L
571 
572 template <typename F, std::size_t... I>
573 void invokeWithStandardMetadata(F&& f, StandardMetadataType type, std::index_sequence<I...>) {
574     // Setup the jump table, mapping from each type to a springboard that invokes the template
575     // function with the appropriate concrete type
576     using F_PTR = decltype(&f);
577     using THUNK = void (*)(F_PTR);
578     static constexpr auto jump = std::array<THUNK, sizeof...(I)>{[](F_PTR fp) {
579         constexpr StandardMetadataType type = ndk::internal::enum_values<StandardMetadataType>[I];
580         if constexpr (type != StandardMetadataType::INVALID) {
581             (*fp)(StandardMetadata<type>{});
582         }
583     }...};
584 
585     auto index = static_cast<size_t>(type);
586     if (index >= 0 && index < jump.size()) {
587         jump[index](&f);
588     }
589 }
590 
591 template <typename F, typename StandardMetadataSequence = std::make_index_sequence<
592                               ndk::internal::enum_values<StandardMetadataType>.size()>>
593 int32_t provideStandardMetadata(StandardMetadataType type, void* _Nullable destBuffer,
594                                 size_t destBufferSize, F&& f) {
595     int32_t retVal = -AIMAPPER_ERROR_UNSUPPORTED;
596     invokeWithStandardMetadata(
597             [&]<StandardMetadataType T>(StandardMetadata<T>) {
598                 retVal = f.template operator()<T>(
599                         [&](const typename StandardMetadata<T>::value_type& value) -> int32_t {
600                             return StandardMetadata<T>::value::encode(value, destBuffer,
601                                                                       destBufferSize);
602                         });
603             },
604             type, StandardMetadataSequence{});
605     return retVal;
606 }
607 
608 template <typename F, typename StandardMetadataSequence = std::make_index_sequence<
609                               ndk::internal::enum_values<StandardMetadataType>.size()>>
610 AIMapper_Error applyStandardMetadata(StandardMetadataType type, const void* _Nonnull metadata,
611                                      size_t metadataSize, F&& f) {
612     AIMapper_Error retVal = AIMAPPER_ERROR_UNSUPPORTED;
613     invokeWithStandardMetadata(
614             [&]<StandardMetadataType T>(StandardMetadata<T>) {
615                 auto value = StandardMetadata<T>::value::decode(metadata, metadataSize);
616                 if (value.has_value()) {
617                     retVal = f.template operator()<T>(std::move(*value));
618                 } else {
619                     retVal = AIMAPPER_ERROR_BAD_VALUE;
620                 }
621             },
622             type, StandardMetadataSequence{});
623     return retVal;
624 }
625 
626 #endif
627 
628 }  // namespace android::hardware::graphics::mapper