Conversion.h revision fa7e967494cde81d93fba94103796f65b9e1202f
1/*
2 * Copyright 2016, 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#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
18#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
19
20#include <vector>
21#include <list>
22
23#include <unistd.h>
24
25#include <hidl/MQDescriptor.h>
26#include <hidl/Status.h>
27#include <hidlmemory/mapping.h>
28
29#include <binder/Binder.h>
30#include <binder/Status.h>
31#include <ui/FenceTime.h>
32#include <cutils/native_handle.h>
33#include <gui/IGraphicBufferProducer.h>
34
35#include <media/OMXFenceParcelable.h>
36#include <media/OMXBuffer.h>
37#include <media/hardware/VideoAPI.h>
38
39#include <android/hidl/memory/1.0/IMemory.h>
40#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
41#include <android/hardware/media/omx/1.0/types.h>
42#include <android/hardware/media/omx/1.0/IOmx.h>
43#include <android/hardware/media/omx/1.0/IOmxNode.h>
44#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
45#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
46#include <android/hardware/media/omx/1.0/IOmxObserver.h>
47
48#include <android/IGraphicBufferSource.h>
49#include <android/IOMXBufferSource.h>
50
51namespace android {
52namespace hardware {
53namespace media {
54namespace omx {
55namespace V1_0 {
56namespace implementation {
57
58using ::android::hardware::hidl_array;
59using ::android::hardware::hidl_string;
60using ::android::hardware::hidl_vec;
61using ::android::hardware::hidl_handle;
62using ::android::hardware::Return;
63using ::android::hardware::Void;
64using ::android::sp;
65
66using ::android::String8;
67using ::android::OMXFenceParcelable;
68
69using ::android::hardware::media::omx::V1_0::Message;
70using ::android::omx_message;
71
72using ::android::hardware::media::omx::V1_0::ColorAspects;
73using ::android::hardware::media::V1_0::Rect;
74using ::android::hardware::media::V1_0::Region;
75
76using ::android::hardware::graphics::common::V1_0::Dataspace;
77
78using ::android::hardware::graphics::common::V1_0::PixelFormat;
79
80using ::android::OMXBuffer;
81
82using ::android::hardware::media::V1_0::AnwBuffer;
83using ::android::GraphicBuffer;
84
85using ::android::hardware::media::omx::V1_0::IOmx;
86using ::android::IOMX;
87
88using ::android::hardware::media::omx::V1_0::IOmxNode;
89using ::android::IOMXNode;
90
91using ::android::hardware::media::omx::V1_0::IOmxObserver;
92using ::android::IOMXObserver;
93
94using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
95using ::android::IOMXBufferSource;
96
97typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
98        HGraphicBufferProducer;
99typedef ::android::IGraphicBufferProducer
100        BGraphicBufferProducer;
101
102// native_handle_t helper functions.
103
104/**
105 * \brief Take an fd and create a native handle containing only the given fd.
106 * The created handle will need to be deleted manually with
107 * `native_handle_delete()`.
108 *
109 * \param[in] fd The source file descriptor (of type `int`).
110 * \return The create `native_handle_t*` that contains the given \p fd. If the
111 * supplied \p fd is negative, the created native handle will contain no file
112 * descriptors.
113 *
114 * If the native handle cannot be created, the return value will be
115 * `nullptr`.
116 *
117 * This function does not duplicate the file descriptor.
118 */
119inline native_handle_t* native_handle_create_from_fd(int fd) {
120    if (fd < 0) {
121        return native_handle_create(0, 0);
122    }
123    native_handle_t* nh = native_handle_create(1, 0);
124    if (nh == nullptr) {
125        return nullptr;
126    }
127    nh->data[0] = fd;
128    return nh;
129}
130
131/**
132 * \brief Extract a file descriptor from a native handle.
133 *
134 * \param[in] nh The source `native_handle_t*`.
135 * \param[in] index The index of the file descriptor in \p nh to read from. This
136 * input has the default value of `0`.
137 * \return The `index`-th file descriptor in \p nh. If \p nh does not have
138 * enough file descriptors, the returned value will be `-1`.
139 *
140 * This function does not duplicate the file descriptor.
141 */
142inline int native_handle_read_fd(native_handle_t const* nh, int index = 0) {
143    return ((nh == nullptr) || (nh->numFds == 0) ||
144            (nh->numFds <= index) || (index < 0)) ?
145            -1 : nh->data[index];
146}
147
148/**
149 * Conversion functions
150 * ====================
151 *
152 * There are two main directions of conversion:
153 * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
154 *   input. The wrapper has type `TargetType`.
155 * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
156 *   corresponds to the input. The lifetime of the output does not depend on the
157 *   lifetime of the input.
158 * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
159 *   that cannot be copied and/or moved efficiently, or when there are multiple
160 *   output arguments.
161 * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
162 *   `TargetType` that cannot be copied and/or moved efficiently, or when there
163 *   are multiple output arguments.
164 *
165 * `wrapIn()` and `convertTo()` functions will take output arguments before
166 * input arguments. Some of these functions might return a value to indicate
167 * success or error.
168 *
169 * In converting or wrapping something as a Treble type that contains a
170 * `hidl_handle`, `native_handle_t*` will need to be created and returned as
171 * an additional output argument, hence only `wrapIn()` or `convertTo()` would
172 * be available. The caller must call `native_handle_delete()` to deallocate the
173 * returned native handle when it is no longer needed.
174 *
175 * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
176 * not perform duplication of file descriptors, while `toTargetType()` and
177 * `convertTo()` do.
178 */
179
180/**
181 * \brief Convert `Return<void>` to `binder::Status`.
182 *
183 * \param[in] t The source `Return<void>`.
184 * \return The corresponding `binder::Status`.
185 */
186// convert: Return<void> -> ::android::binder::Status
187inline ::android::binder::Status toBinderStatus(
188        Return<void> const& t) {
189    return ::android::binder::Status::fromExceptionCode(
190            t.isOk() ? OK : UNKNOWN_ERROR,
191            t.description().c_str());
192}
193
194/**
195 * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder
196 * calls.
197 *
198 * \param[in] t The source `Return<Status>`.
199 * \return The corresponding `status_t`.
200 *
201 * This function first check if \p t has a transport error. If it does, then the
202 * return value is the transport error code. Otherwise, the return value is
203 * converted from `Status` contained inside \p t.
204 *
205 * Note:
206 * - This `Status` is omx-specific. It is defined in `types.hal`.
207 * - The name of this function is not `convert`.
208 */
209// convert: Status -> status_t
210inline status_t toStatusT(Return<Status> const& t) {
211    return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR;
212}
213
214/**
215 * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
216 *
217 * \param[in] t The source `Return<void>`.
218 * \return The corresponding `status_t`.
219 */
220// convert: Return<void> -> status_t
221inline status_t toStatusT(Return<void> const& t) {
222    return t.isOk() ? OK : UNKNOWN_ERROR;
223}
224
225/**
226 * \brief Convert `Status` to `status_t`. This is for legacy binder calls.
227 *
228 * \param[in] t The source `Status`.
229 * \return the corresponding `status_t`.
230 */
231// convert: Status -> status_t
232inline status_t toStatusT(Status const& t) {
233    return static_cast<status_t>(t);
234}
235
236/**
237 * \brief Convert `status_t` to `Status`.
238 *
239 * \param[in] l The source `status_t`.
240 * \return The corresponding `Status`.
241 */
242// convert: status_t -> Status
243inline Status toStatus(status_t l) {
244    return static_cast<Status>(l);
245}
246
247/**
248 * \brief Wrap `native_handle_t*` in `hidl_handle`.
249 *
250 * \param[in] nh The source `native_handle_t*`.
251 * \return The `hidl_handle` that points to \p nh.
252 */
253// wrap: native_handle_t* -> hidl_handle
254inline hidl_handle inHidlHandle(native_handle_t const* nh) {
255    return hidl_handle(nh);
256}
257
258/**
259 * \brief Wrap an `omx_message` and construct the corresponding `Message`.
260 *
261 * \param[out] t The wrapper of type `Message`.
262 * \param[out] nh The native_handle_t referred to by `t->fence`.
263 * \param[in] l The source `omx_message`.
264 * \return `true` if the wrapping is successful; `false` otherwise.
265 *
266 * Upon success, \p nh will be created to hold the file descriptor stored in
267 * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be
268 * destroyed manually by `native_handle_delete()` when \p t is no longer needed.
269 *
270 * Upon failure, \p nh will not be created and will not need to be deleted. \p t
271 * will be invalid.
272 */
273// wrap, omx_message -> Message, native_handle_t*
274inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) {
275    *nh = native_handle_create_from_fd(l.fenceFd);
276    if (!*nh) {
277        return false;
278    }
279    t->fence = *nh;
280    switch (l.type) {
281        case omx_message::EVENT:
282            t->type = Message::Type::EVENT;
283            t->data.eventData.event = uint32_t(l.u.event_data.event);
284            t->data.eventData.data1 = l.u.event_data.data1;
285            t->data.eventData.data2 = l.u.event_data.data2;
286            t->data.eventData.data3 = l.u.event_data.data3;
287            t->data.eventData.data4 = l.u.event_data.data4;
288            break;
289        case omx_message::EMPTY_BUFFER_DONE:
290            t->type = Message::Type::EMPTY_BUFFER_DONE;
291            t->data.bufferData.buffer = l.u.buffer_data.buffer;
292            break;
293        case omx_message::FILL_BUFFER_DONE:
294            t->type = Message::Type::FILL_BUFFER_DONE;
295            t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer;
296            t->data.extendedBufferData.rangeOffset =
297                    l.u.extended_buffer_data.range_offset;
298            t->data.extendedBufferData.rangeLength =
299                    l.u.extended_buffer_data.range_length;
300            t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags;
301            t->data.extendedBufferData.timestampUs =
302                    l.u.extended_buffer_data.timestamp;
303            break;
304        case omx_message::FRAME_RENDERED:
305            t->type = Message::Type::FRAME_RENDERED;
306            t->data.renderData.timestampUs = l.u.render_data.timestamp;
307            t->data.renderData.systemTimeNs = l.u.render_data.nanoTime;
308            break;
309        default:
310            native_handle_delete(*nh);
311            return false;
312    }
313    return true;
314}
315
316/**
317 * \brief Wrap a `Message` inside an `omx_message`.
318 *
319 * \param[out] l The wrapper of type `omx_message`.
320 * \param[in] t The source `Message`.
321 * \return `true` if the wrapping is successful; `false` otherwise.
322 */
323// wrap: Message -> omx_message
324inline bool wrapAs(omx_message* l, Message const& t) {
325    l->fenceFd = native_handle_read_fd(t.fence);
326    switch (t.type) {
327        case Message::Type::EVENT:
328            l->type = omx_message::EVENT;
329            l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event);
330            l->u.event_data.data1 = t.data.eventData.data1;
331            l->u.event_data.data2 = t.data.eventData.data2;
332            l->u.event_data.data3 = t.data.eventData.data3;
333            l->u.event_data.data4 = t.data.eventData.data4;
334            break;
335        case Message::Type::EMPTY_BUFFER_DONE:
336            l->type = omx_message::EMPTY_BUFFER_DONE;
337            l->u.buffer_data.buffer = t.data.bufferData.buffer;
338            break;
339        case Message::Type::FILL_BUFFER_DONE:
340            l->type = omx_message::FILL_BUFFER_DONE;
341            l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer;
342            l->u.extended_buffer_data.range_offset =
343                    t.data.extendedBufferData.rangeOffset;
344            l->u.extended_buffer_data.range_length =
345                    t.data.extendedBufferData.rangeLength;
346            l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags;
347            l->u.extended_buffer_data.timestamp =
348                    t.data.extendedBufferData.timestampUs;
349            break;
350        case Message::Type::FRAME_RENDERED:
351            l->type = omx_message::FRAME_RENDERED;
352            l->u.render_data.timestamp = t.data.renderData.timestampUs;
353            l->u.render_data.nanoTime = t.data.renderData.systemTimeNs;
354            break;
355        default:
356            return false;
357    }
358    return true;
359}
360
361/**
362 * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will
363 * have an extended lifetime.
364 *
365 * \param[out] l The output `omx_message`.
366 * \param[in] t The source `Message`.
367 * \return `true` if the conversion is successful; `false` otherwise.
368 *
369 * This function calls `wrapto()`, then attempts to duplicate the file
370 * descriptor for the fence if it is not `-1`. If duplication fails, `false`
371 * will be returned.
372 */
373// convert: Message -> omx_message
374inline bool convertTo(omx_message* l, Message const& t) {
375    if (!wrapAs(l, t)) {
376        return false;
377    }
378    if (l->fenceFd == -1) {
379        return true;
380    }
381    l->fenceFd = dup(l->fenceFd);
382    return l->fenceFd != -1;
383}
384
385/**
386 * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`.
387 *
388 * \param[out] t The wrapper of type `hidl_handle`.
389 * \param[out] nh The native handle created to hold the file descriptor inside
390 * \p l.
391 * \param[in] l The source `OMXFenceParcelable`, which essentially contains one
392 * file descriptor.
393 * \return `true` if \p t and \p nh are successfully created to wrap around \p
394 * l; `false` otherwise.
395 *
396 * On success, \p nh needs to be deleted by the caller with
397 * `native_handle_delete()` after \p t and \p nh are no longer needed.
398 *
399 * On failure, \p nh will not need to be deleted, and \p t will hold an invalid
400 * value.
401 */
402// wrap: OMXFenceParcelable -> hidl_handle, native_handle_t*
403inline bool wrapAs(hidl_handle* t, native_handle_t** nh,
404        OMXFenceParcelable const& l) {
405    *nh = native_handle_create_from_fd(l.get());
406    if (!*nh) {
407        return false;
408    }
409    *t = *nh;
410    return true;
411}
412
413/**
414 * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`.
415 *
416 * \param[out] l The wrapper of type `OMXFenceParcelable`.
417 * \param[in] t The source `hidl_handle`.
418 */
419// wrap: hidl_handle -> OMXFenceParcelable
420inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) {
421    l->mFenceFd = native_handle_read_fd(t);
422}
423
424/**
425 * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle`
426 * contains file descriptors, the first file descriptor will be duplicated and
427 * stored in the output `OMXFenceParcelable`.
428 *
429 * \param[out] l The output `OMXFenceParcelable`.
430 * \param[in] t The input `hidl_handle`.
431 * \return `false` if \p t contains a valid file descriptor but duplication
432 * fails; `true` otherwise.
433 */
434// convert: hidl_handle -> OMXFenceParcelable
435inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) {
436    int fd = native_handle_read_fd(t);
437    if (fd != -1) {
438        fd = dup(fd);
439        if (fd == -1) {
440            return false;
441        }
442    }
443    l->mFenceFd = fd;
444    return true;
445}
446
447/**
448 * \brief Convert `::android::ColorAspects` to `ColorAspects`.
449 *
450 * \param[in] l The source `::android::ColorAspects`.
451 * \return The corresponding `ColorAspects`.
452 */
453// convert: ::android::ColorAspects -> ColorAspects
454inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) {
455    return ColorAspects{
456            static_cast<ColorAspects::Range>(l.mRange),
457            static_cast<ColorAspects::Primaries>(l.mPrimaries),
458            static_cast<ColorAspects::Transfer>(l.mTransfer),
459            static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)};
460}
461
462/**
463 * \brief Convert `int32_t` to `ColorAspects`.
464 *
465 * \param[in] l The source `int32_t`.
466 * \return The corresponding `ColorAspects`.
467 */
468// convert: int32_t -> ColorAspects
469inline ColorAspects toHardwareColorAspects(int32_t l) {
470    return ColorAspects{
471            static_cast<ColorAspects::Range>((l >> 24) & 0xFF),
472            static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF),
473            static_cast<ColorAspects::Transfer>(l & 0xFF),
474            static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)};
475}
476
477/**
478 * \brief Convert `ColorAspects` to `::android::ColorAspects`.
479 *
480 * \param[in] t The source `ColorAspects`.
481 * \return The corresponding `::android::ColorAspects`.
482 */
483// convert: ColorAspects -> ::android::ColorAspects
484inline int32_t toCompactColorAspects(ColorAspects const& t) {
485    return static_cast<int32_t>(
486            (static_cast<uint32_t>(t.range) << 24) |
487            (static_cast<uint32_t>(t.primaries) << 16) |
488            (static_cast<uint32_t>(t.transfer)) |
489            (static_cast<uint32_t>(t.matrixCoeffs) << 8));
490}
491
492/**
493 * \brief Convert `int32_t` to `Dataspace`.
494 *
495 * \param[in] l The source `int32_t`.
496 * \result The corresponding `Dataspace`.
497 */
498// convert: int32_t -> Dataspace
499inline Dataspace toHardwareDataspace(int32_t l) {
500    return static_cast<Dataspace>(l);
501}
502
503/**
504 * \brief Convert `Dataspace` to `int32_t`.
505 *
506 * \param[in] t The source `Dataspace`.
507 * \result The corresponding `int32_t`.
508 */
509// convert: Dataspace -> int32_t
510inline int32_t toRawDataspace(Dataspace const& t) {
511    return static_cast<int32_t>(t);
512}
513
514/**
515 * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
516 *
517 * \param[in] l The pointer to the beginning of the opaque buffer.
518 * \param[in] size The size of the buffer.
519 * \return A `hidl_vec<uint8_t>` that points to the buffer.
520 */
521// wrap: void*, size_t -> hidl_vec<uint8_t>
522inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
523    hidl_vec<uint8_t> t;
524    t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
525    return t;
526}
527
528/**
529 * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
530 *
531 * \param[in] l The pointer to the beginning of the opaque buffer.
532 * \param[in] size The size of the buffer.
533 * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
534 */
535// convert: void*, size_t -> hidl_vec<uint8_t>
536inline hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
537    hidl_vec<uint8_t> t;
538    t.resize(size);
539    uint8_t const* src = static_cast<uint8_t const*>(l);
540    std::copy(src, src + size, t.data());
541    return t;
542}
543
544/**
545 * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
546 *
547 * \param[out] t The wrapper of type `AnwBuffer`.
548 * \param[in] l The source `GraphicBuffer`.
549 */
550// wrap: GraphicBuffer -> AnwBuffer
551inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
552    t->attr.width = l.getWidth();
553    t->attr.height = l.getHeight();
554    t->attr.stride = l.getStride();
555    t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
556    t->attr.layerCount = l.getLayerCount();
557    t->attr.usage = l.getUsage();
558    t->attr.id = l.getId();
559    t->attr.generationNumber = l.getGenerationNumber();
560    t->nativeHandle = hidl_handle(l.handle);
561}
562
563/**
564 * \brief Convert `AnwBuffer` to `GraphicBuffer`.
565 *
566 * \param[out] l The destination `GraphicBuffer`.
567 * \param[in] t The source `AnwBuffer`.
568 *
569 * This function will duplicate all file descriptors in \p t.
570 */
571// convert: AnwBuffer -> GraphicBuffer
572// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
573inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
574    native_handle_t* handle = t.nativeHandle == nullptr ?
575            nullptr : native_handle_clone(t.nativeHandle);
576
577    size_t const numInts = 12 + (handle ? handle->numInts : 0);
578    int32_t* ints = new int32_t[numInts];
579
580    size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
581    int* fds = new int[numFds];
582
583    ints[0] = 'GBFR';
584    ints[1] = static_cast<int32_t>(t.attr.width);
585    ints[2] = static_cast<int32_t>(t.attr.height);
586    ints[3] = static_cast<int32_t>(t.attr.stride);
587    ints[4] = static_cast<int32_t>(t.attr.format);
588    ints[5] = static_cast<int32_t>(t.attr.layerCount);
589    ints[6] = static_cast<int32_t>(t.attr.usage);
590    ints[7] = static_cast<int32_t>(t.attr.id >> 32);
591    ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
592    ints[9] = static_cast<int32_t>(t.attr.generationNumber);
593    ints[10] = 0;
594    ints[11] = 0;
595    if (handle) {
596        ints[10] = static_cast<int32_t>(handle->numFds);
597        ints[11] = static_cast<int32_t>(handle->numInts);
598        int* intsStart = handle->data + handle->numFds;
599        std::copy(handle->data, intsStart, fds);
600        std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
601    }
602
603    void const* constBuffer = static_cast<void const*>(ints);
604    size_t size = numInts * sizeof(int32_t);
605    int const* constFds = static_cast<int const*>(fds);
606    status_t status = l->unflatten(constBuffer, size, constFds, numFds);
607
608    delete [] fds;
609    delete [] ints;
610    native_handle_delete(handle);
611    return status == NO_ERROR;
612}
613
614/**
615 * \brief Wrap `GraphicBuffer` in `CodecBuffer`.
616 *
617 * \param[out] t The wrapper of type `CodecBuffer`.
618 * \param[in] l The source `GraphicBuffer`.
619 */
620// wrap: OMXBuffer -> CodecBuffer
621inline CodecBuffer *wrapAs(CodecBuffer *t, sp<GraphicBuffer> const& graphicBuffer) {
622    t->sharedMemory = hidl_memory();
623    t->nativeHandle = hidl_handle();
624    t->type = CodecBuffer::Type::ANW_BUFFER;
625    if (graphicBuffer == nullptr) {
626        t->attr.anwBuffer.width = 0;
627        t->attr.anwBuffer.height = 0;
628        t->attr.anwBuffer.stride = 0;
629        t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
630        t->attr.anwBuffer.layerCount = 0;
631        t->attr.anwBuffer.usage = 0;
632        return t;
633    }
634    t->attr.anwBuffer.width = graphicBuffer->getWidth();
635    t->attr.anwBuffer.height = graphicBuffer->getHeight();
636    t->attr.anwBuffer.stride = graphicBuffer->getStride();
637    t->attr.anwBuffer.format = static_cast<PixelFormat>(
638            graphicBuffer->getPixelFormat());
639    t->attr.anwBuffer.layerCount = graphicBuffer->getLayerCount();
640    t->attr.anwBuffer.usage = graphicBuffer->getUsage();
641    t->nativeHandle = graphicBuffer->handle;
642    return t;
643}
644
645/**
646 * \brief Wrap `OMXBuffer` in `CodecBuffer`.
647 *
648 * \param[out] t The wrapper of type `CodecBuffer`.
649 * \param[in] l The source `OMXBuffer`.
650 * \return `true` if the wrapping is successful; `false` otherwise.
651 */
652// wrap: OMXBuffer -> CodecBuffer
653inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) {
654    t->sharedMemory = hidl_memory();
655    t->nativeHandle = hidl_handle();
656    switch (l.mBufferType) {
657        case OMXBuffer::kBufferTypeInvalid: {
658            t->type = CodecBuffer::Type::INVALID;
659            return true;
660        }
661        case OMXBuffer::kBufferTypePreset: {
662            t->type = CodecBuffer::Type::PRESET;
663            t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength);
664            t->attr.preset.rangeOffset = static_cast<uint32_t>(l.mRangeOffset);
665            return true;
666        }
667        case OMXBuffer::kBufferTypeHidlMemory: {
668            t->type = CodecBuffer::Type::SHARED_MEM;
669            t->sharedMemory = l.mHidlMemory;
670            return true;
671        }
672        case OMXBuffer::kBufferTypeSharedMem: {
673            // This is not supported.
674            return false;
675        }
676        case OMXBuffer::kBufferTypeANWBuffer: {
677            wrapAs(t, l.mGraphicBuffer);
678            return true;
679        }
680        case OMXBuffer::kBufferTypeNativeHandle: {
681            t->type = CodecBuffer::Type::NATIVE_HANDLE;
682            t->nativeHandle = l.mNativeHandle->handle();
683            return true;
684        }
685    }
686    return false;
687}
688
689/**
690 * \brief Convert `CodecBuffer` to `OMXBuffer`.
691 *
692 * \param[out] l The destination `OMXBuffer`.
693 * \param[in] t The source `CodecBuffer`.
694 * \return `true` if successful; `false` otherwise.
695 */
696// convert: CodecBuffer -> OMXBuffer
697inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) {
698    switch (t.type) {
699        case CodecBuffer::Type::INVALID: {
700            *l = OMXBuffer();
701            return true;
702        }
703        case CodecBuffer::Type::PRESET: {
704            *l = OMXBuffer(
705                    t.attr.preset.rangeOffset,
706                    t.attr.preset.rangeLength);
707            return true;
708        }
709        case CodecBuffer::Type::SHARED_MEM: {
710            *l = OMXBuffer(t.sharedMemory);
711            return true;
712        }
713        case CodecBuffer::Type::ANW_BUFFER: {
714            if (t.nativeHandle.getNativeHandle() == nullptr) {
715                *l = OMXBuffer(sp<GraphicBuffer>(nullptr));
716                return true;
717            }
718            AnwBuffer anwBuffer;
719            anwBuffer.nativeHandle = t.nativeHandle;
720            anwBuffer.attr = t.attr.anwBuffer;
721            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
722            if (!convertTo(graphicBuffer.get(), anwBuffer)) {
723                return false;
724            }
725            *l = OMXBuffer(graphicBuffer);
726            return true;
727        }
728        case CodecBuffer::Type::NATIVE_HANDLE: {
729            *l = OMXBuffer(NativeHandle::create(
730                    native_handle_clone(t.nativeHandle), true));
731            return true;
732        }
733    }
734    return false;
735}
736
737/**
738 * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`.
739 *
740 * \param[out] t The destination `IOmx::ComponentInfo`.
741 * \param[in] l The source `IOMX::ComponentInfo`.
742 */
743// convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
744inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
745    t->mName = l.mName.string();
746    t->mRoles.resize(l.mRoles.size());
747    size_t i = 0;
748    for (auto& role : l.mRoles) {
749        t->mRoles[i++] = role.string();
750    }
751    return true;
752}
753
754/**
755 * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`.
756 *
757 * \param[out] l The destination `IOMX::ComponentInfo`.
758 * \param[in] t The source `IOmx::ComponentInfo`.
759 */
760// convert: IOmx::ComponentInfo -> IOMX::ComponentInfo
761inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) {
762    l->mName = t.mName.c_str();
763    l->mRoles.clear();
764    for (size_t i = 0; i < t.mRoles.size(); ++i) {
765        l->mRoles.push_back(String8(t.mRoles[i].c_str()));
766    }
767    return true;
768}
769
770/**
771 * \brief Convert `OMX_BOOL` to `bool`.
772 *
773 * \param[in] l The source `OMX_BOOL`.
774 * \return The destination `bool`.
775 */
776// convert: OMX_BOOL -> bool
777inline bool toRawBool(OMX_BOOL l) {
778    return l == OMX_FALSE ? false : true;
779}
780
781/**
782 * \brief Convert `bool` to `OMX_BOOL`.
783 *
784 * \param[in] t The source `bool`.
785 * \return The destination `OMX_BOOL`.
786 */
787// convert: bool -> OMX_BOOL
788inline OMX_BOOL toEnumBool(bool t) {
789    return t ? OMX_TRUE : OMX_FALSE;
790}
791
792/**
793 * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`.
794 *
795 * \param[in] l The source `OMX_COMMANDTYPE`.
796 * \return The underlying value of type `uint32_t`.
797 *
798 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
799 */
800// convert: OMX_COMMANDTYPE -> uint32_t
801inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
802    return static_cast<uint32_t>(l);
803}
804
805/**
806 * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`.
807 *
808 * \param[in] t The source `uint32_t`.
809 * \return The corresponding enum value of type `OMX_COMMANDTYPE`.
810 *
811 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
812 */
813// convert: uint32_t -> OMX_COMMANDTYPE
814inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) {
815    return static_cast<OMX_COMMANDTYPE>(t);
816}
817
818/**
819 * \brief Convert `OMX_INDEXTYPE` to `uint32_t`.
820 *
821 * \param[in] l The source `OMX_INDEXTYPE`.
822 * \return The underlying value of type `uint32_t`.
823 *
824 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
825 */
826// convert: OMX_INDEXTYPE -> uint32_t
827inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
828    return static_cast<uint32_t>(l);
829}
830
831/**
832 * \brief Convert `uint32_t` to `OMX_INDEXTYPE`.
833 *
834 * \param[in] t The source `uint32_t`.
835 * \return The corresponding enum value of type `OMX_INDEXTYPE`.
836 *
837 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
838 */
839// convert: uint32_t -> OMX_INDEXTYPE
840inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) {
841    return static_cast<OMX_INDEXTYPE>(t);
842}
843
844/**
845 * \brief Convert `IOMX::PortMode` to `PortMode`.
846 *
847 * \param[in] l The source `IOMX::PortMode`.
848 * \return The destination `PortMode`.
849 */
850// convert: IOMX::PortMode -> PortMode
851inline PortMode toHardwarePortMode(IOMX::PortMode l) {
852    return static_cast<PortMode>(l);
853}
854
855/**
856 * \brief Convert `PortMode` to `IOMX::PortMode`.
857 *
858 * \param[in] t The source `PortMode`.
859 * \return The destination `IOMX::PortMode`.
860 */
861// convert: PortMode -> IOMX::PortMode
862inline IOMX::PortMode toIOMXPortMode(PortMode t) {
863    return static_cast<IOMX::PortMode>(t);
864}
865
866/**
867 * \brief Convert `OMX_TICKS` to `uint64_t`.
868 *
869 * \param[in] l The source `OMX_TICKS`.
870 * \return The destination `uint64_t`.
871 */
872// convert: OMX_TICKS -> uint64_t
873inline uint64_t toRawTicks(OMX_TICKS l) {
874#ifndef OMX_SKIP64BIT
875    return static_cast<uint64_t>(l);
876#else
877    return static_cast<uint64_t>(l.nLowPart) |
878            static_cast<uint64_t>(l.nHighPart << 32);
879#endif
880}
881
882/**
883 * \brief Convert `uint64_t` to `OMX_TICKS`.
884 *
885 * \param[in] l The source `uint64_t`.
886 * \return The destination `OMX_TICKS`.
887 */
888// convert: uint64_t -> OMX_TICKS
889inline OMX_TICKS toOMXTicks(uint64_t t) {
890#ifndef OMX_SKIP64BIT
891    return static_cast<OMX_TICKS>(t);
892#else
893    return OMX_TICKS{
894            static_cast<uint32_t>(t & 0xFFFFFFFF),
895            static_cast<uint32_t>(t >> 32)};
896#endif
897}
898
899/**
900 * Conversion functions for types outside media
901 * ============================================
902 *
903 * Some objects in libui and libgui that were made to go through binder calls do
904 * not expose ways to read or write their fields to the public. To pass an
905 * object of this kind through the HIDL boundary, translation functions need to
906 * work around the access restriction by using the publicly available
907 * `flatten()` and `unflatten()` functions.
908 *
909 * All `flatten()` and `unflatten()` overloads follow the same convention as
910 * follows:
911 *
912 *     status_t flatten(ObjectType const& object,
913 *                      [OtherType const& other, ...]
914 *                      void*& buffer, size_t& size,
915 *                      int*& fds, size_t& numFds)
916 *
917 *     status_t unflatten(ObjectType* object,
918 *                        [OtherType* other, ...,]
919 *                        void*& buffer, size_t& size,
920 *                        int*& fds, size_t& numFds)
921 *
922 * The number of `other` parameters varies depending on the `ObjectType`. For
923 * example, in the process of unflattening an object that contains
924 * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
925 * be created.
926 *
927 * The last four parameters always work the same way in all overloads of
928 * `flatten()` and `unflatten()`:
929 * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
930 *   `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
931 *   `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
932 *   size (in ints) of the fd buffer pointed to by `fds`.
933 * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
934 *   from, `size` is the size (in bytes) of the non-fd buffer pointed to by
935 *   `buffer`, `fds` is the pointer to the fd buffer to be read from, and
936 *   `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
937 * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
938 *   will be advanced, while `size` and `numFds` will be decreased to reflect
939 *   how much storage/data of the two buffers (fd and non-fd) have been used.
940 * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
941 *   `numFds` are invalid.
942 *
943 * The return value of a successful `flatten()` or `unflatten()` call will be
944 * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
945 *
946 * For each object type that supports flattening, there will be two accompanying
947 * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
948 * return the size of the non-fd buffer that the object will need for
949 * flattening. `getFdCount()` will return the size of the fd buffer that the
950 * object will need for flattening.
951 *
952 * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
953 * `flatten()` and `unflatten()`, are similar to functions of the same name in
954 * the abstract class `Flattenable`. The only difference is that functions in
955 * this file are not member functions of the object type. For example, we write
956 *
957 *     flatten(x, buffer, size, fds, numFds)
958 *
959 * instead of
960 *
961 *     x.flatten(buffer, size, fds, numFds)
962 *
963 * because we cannot modify the type of `x`.
964 *
965 * There is one exception to the naming convention: `hidl_handle` that
966 * represents a fence. The four functions for this "Fence" type have the word
967 * "Fence" attched to their names because the object type, which is
968 * `hidl_handle`, does not carry the special meaning that the object itself can
969 * only contain zero or one file descriptor.
970 */
971
972// Ref: frameworks/native/libs/ui/Fence.cpp
973
974/**
975 * \brief Return the size of the non-fd buffer required to flatten a fence.
976 *
977 * \param[in] fence The input fence of type `hidl_handle`.
978 * \return The required size of the flat buffer.
979 *
980 * The current version of this function always returns 4, which is the number of
981 * bytes required to store the number of file descriptors contained in the fd
982 * part of the flat buffer.
983 */
984inline size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
985    return 4;
986};
987
988/**
989 * \brief Return the number of file descriptors contained in a fence.
990 *
991 * \param[in] fence The input fence of type `hidl_handle`.
992 * \return `0` if \p fence does not contain a valid file descriptor, or `1`
993 * otherwise.
994 */
995inline size_t getFenceFdCount(hidl_handle const& fence) {
996    return native_handle_read_fd(fence) == -1 ? 0 : 1;
997}
998
999/**
1000 * \brief Unflatten `Fence` to `hidl_handle`.
1001 *
1002 * \param[out] fence The destination `hidl_handle`.
1003 * \param[out] nh The underlying native handle.
1004 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1005 * \param[in,out] size The size of the flat non-fd buffer.
1006 * \param[in,out] fds The pointer to the flat fd buffer.
1007 * \param[in,out] numFds The size of the flat fd buffer.
1008 * \return `NO_ERROR` on success; other value on failure.
1009 *
1010 * If the return value is `NO_ERROR`, \p nh will point to a newly created
1011 * native handle, which needs to be deleted with `native_handle_delete()`
1012 * afterwards.
1013 */
1014inline status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
1015        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1016    if (size < 4) {
1017        return NO_MEMORY;
1018    }
1019
1020    uint32_t numFdsInHandle;
1021    FlattenableUtils::read(buffer, size, numFdsInHandle);
1022
1023    if (numFdsInHandle > 1) {
1024        return BAD_VALUE;
1025    }
1026
1027    if (numFds < numFdsInHandle) {
1028        return NO_MEMORY;
1029    }
1030
1031    if (numFdsInHandle) {
1032        *nh = native_handle_create_from_fd(*fds);
1033        if (*nh == nullptr) {
1034            return NO_MEMORY;
1035        }
1036        *fence = *nh;
1037        ++fds;
1038        --numFds;
1039    } else {
1040        *nh = nullptr;
1041        *fence = hidl_handle();
1042    }
1043
1044    return NO_ERROR;
1045}
1046
1047/**
1048 * \brief Flatten `hidl_handle` as `Fence`.
1049 *
1050 * \param[in] t The source `hidl_handle`.
1051 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1052 * \param[in,out] size The size of the flat non-fd buffer.
1053 * \param[in,out] fds The pointer to the flat fd buffer.
1054 * \param[in,out] numFds The size of the flat fd buffer.
1055 * \return `NO_ERROR` on success; other value on failure.
1056 */
1057inline status_t flattenFence(hidl_handle const& fence,
1058        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1059    if (size < getFenceFlattenedSize(fence) ||
1060            numFds < getFenceFdCount(fence)) {
1061        return NO_MEMORY;
1062    }
1063    // Cast to uint32_t since the size of a size_t can vary between 32- and
1064    // 64-bit processes
1065    FlattenableUtils::write(buffer, size,
1066            static_cast<uint32_t>(getFenceFdCount(fence)));
1067    int fd = native_handle_read_fd(fence);
1068    if (fd != -1) {
1069        *fds = fd;
1070        ++fds;
1071        --numFds;
1072    }
1073    return NO_ERROR;
1074}
1075
1076/**
1077 * \brief Wrap `Fence` in `hidl_handle`.
1078 *
1079 * \param[out] t The wrapper of type `hidl_handle`.
1080 * \param[out] nh The native handle pointed to by \p t.
1081 * \param[in] l The source `Fence`.
1082 *
1083 * On success, \p nh will hold a newly created native handle, which must be
1084 * deleted manually with `native_handle_delete()` afterwards.
1085 */
1086// wrap: Fence -> hidl_handle
1087inline bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
1088    size_t const baseSize = l.getFlattenedSize();
1089    std::unique_ptr<uint8_t[]> baseBuffer(
1090            new (std::nothrow) uint8_t[baseSize]);
1091    if (!baseBuffer) {
1092        return false;
1093    }
1094
1095    size_t const baseNumFds = l.getFdCount();
1096    std::unique_ptr<int[]> baseFds(
1097            new (std::nothrow) int[baseNumFds]);
1098    if (!baseFds) {
1099        return false;
1100    }
1101
1102    void* buffer = static_cast<void*>(baseBuffer.get());
1103    size_t size = baseSize;
1104    int* fds = static_cast<int*>(baseFds.get());
1105    size_t numFds = baseNumFds;
1106    if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
1107        return false;
1108    }
1109
1110    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1111    size = baseSize;
1112    int const* constFds = static_cast<int const*>(baseFds.get());
1113    numFds = baseNumFds;
1114    if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
1115            != NO_ERROR) {
1116        return false;
1117    }
1118
1119    return true;
1120}
1121
1122/**
1123 * \brief Convert `hidl_handle` to `Fence`.
1124 *
1125 * \param[out] l The destination `Fence`. `l` must not have been used
1126 * (`l->isValid()` must return `false`) before this function is called.
1127 * \param[in] t The source `hidl_handle`.
1128 *
1129 * If \p t contains a valid file descriptor, it will be duplicated.
1130 */
1131// convert: hidl_handle -> Fence
1132inline bool convertTo(Fence* l, hidl_handle const& t) {
1133    int fd = native_handle_read_fd(t);
1134    if (fd != -1) {
1135        fd = dup(fd);
1136        if (fd == -1) {
1137            return false;
1138        }
1139    }
1140    native_handle_t* nh = native_handle_create_from_fd(fd);
1141    if (nh == nullptr) {
1142        if (fd != -1) {
1143            close(fd);
1144        }
1145        return false;
1146    }
1147
1148    size_t const baseSize = getFenceFlattenedSize(t);
1149    std::unique_ptr<uint8_t[]> baseBuffer(
1150            new (std::nothrow) uint8_t[baseSize]);
1151    if (!baseBuffer) {
1152        native_handle_delete(nh);
1153        return false;
1154    }
1155
1156    size_t const baseNumFds = getFenceFdCount(t);
1157    std::unique_ptr<int[]> baseFds(
1158            new (std::nothrow) int[baseNumFds]);
1159    if (!baseFds) {
1160        native_handle_delete(nh);
1161        return false;
1162    }
1163
1164    void* buffer = static_cast<void*>(baseBuffer.get());
1165    size_t size = baseSize;
1166    int* fds = static_cast<int*>(baseFds.get());
1167    size_t numFds = baseNumFds;
1168    if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
1169        native_handle_delete(nh);
1170        return false;
1171    }
1172    native_handle_delete(nh);
1173
1174    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1175    size = baseSize;
1176    int const* constFds = static_cast<int const*>(baseFds.get());
1177    numFds = baseNumFds;
1178    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
1179        return false;
1180    }
1181
1182    return true;
1183}
1184
1185// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
1186
1187/**
1188 * \brief Return the size of the non-fd buffer required to flatten
1189 * `FenceTimeSnapshot`.
1190 *
1191 * \param[in] t The input `FenceTimeSnapshot`.
1192 * \return The required size of the flat buffer.
1193 */
1194inline size_t getFlattenedSize(
1195        HGraphicBufferProducer::FenceTimeSnapshot const& t) {
1196    constexpr size_t min = sizeof(t.state);
1197    switch (t.state) {
1198        case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
1199            return min;
1200        case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
1201            return min + getFenceFlattenedSize(t.fence);
1202        case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
1203            return min + sizeof(
1204                    ::android::FenceTime::Snapshot::signalTime);
1205    }
1206    return 0;
1207}
1208
1209/**
1210 * \brief Return the number of file descriptors contained in
1211 * `FenceTimeSnapshot`.
1212 *
1213 * \param[in] t The input `FenceTimeSnapshot`.
1214 * \return The number of file descriptors contained in \p snapshot.
1215 */
1216inline size_t getFdCount(
1217        HGraphicBufferProducer::FenceTimeSnapshot const& t) {
1218    return t.state ==
1219            HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE ?
1220            getFenceFdCount(t.fence) : 0;
1221}
1222
1223/**
1224 * \brief Flatten `FenceTimeSnapshot`.
1225 *
1226 * \param[in] t The source `FenceTimeSnapshot`.
1227 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1228 * \param[in,out] size The size of the flat non-fd buffer.
1229 * \param[in,out] fds The pointer to the flat fd buffer.
1230 * \param[in,out] numFds The size of the flat fd buffer.
1231 * \return `NO_ERROR` on success; other value on failure.
1232 *
1233 * This function will duplicate the file descriptor in `t.fence` if `t.state ==
1234 * FENCE`.
1235 */
1236inline status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
1237        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1238    if (size < getFlattenedSize(t)) {
1239        return NO_MEMORY;
1240    }
1241
1242    switch (t.state) {
1243        case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
1244            FlattenableUtils::write(buffer, size,
1245                    ::android::FenceTime::Snapshot::State::EMPTY);
1246            return NO_ERROR;
1247        case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
1248            FlattenableUtils::write(buffer, size,
1249                    ::android::FenceTime::Snapshot::State::FENCE);
1250            return flattenFence(t.fence, buffer, size, fds, numFds);
1251        case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
1252            FlattenableUtils::write(buffer, size,
1253                    ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
1254            FlattenableUtils::write(buffer, size, t.signalTimeNs);
1255            return NO_ERROR;
1256    }
1257    return NO_ERROR;
1258}
1259
1260/**
1261 * \brief Unflatten `FenceTimeSnapshot`.
1262 *
1263 * \param[out] t The destination `FenceTimeSnapshot`.
1264 * \param[out] nh The underlying native handle.
1265 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1266 * \param[in,out] size The size of the flat non-fd buffer.
1267 * \param[in,out] fds The pointer to the flat fd buffer.
1268 * \param[in,out] numFds The size of the flat fd buffer.
1269 * \return `NO_ERROR` on success; other value on failure.
1270 *
1271 * If the return value is `NO_ERROR` and the constructed snapshot contains a
1272 * file descriptor, \p nh will be created to hold that file descriptor. In this
1273 * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
1274 */
1275inline status_t unflatten(
1276        HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
1277        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1278    if (size < sizeof(t->state)) {
1279        return NO_MEMORY;
1280    }
1281
1282    *nh = nullptr;
1283    ::android::FenceTime::Snapshot::State state;
1284    FlattenableUtils::read(buffer, size, state);
1285    switch (state) {
1286        case ::android::FenceTime::Snapshot::State::EMPTY:
1287            t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY;
1288            return NO_ERROR;
1289        case ::android::FenceTime::Snapshot::State::FENCE:
1290            t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE;
1291            return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
1292        case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
1293            t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
1294            if (size < sizeof(t->signalTimeNs)) {
1295                return NO_MEMORY;
1296            }
1297            FlattenableUtils::read(buffer, size, t->signalTimeNs);
1298            return NO_ERROR;
1299    }
1300    return NO_ERROR;
1301}
1302
1303// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
1304
1305/**
1306 * \brief Return a lower bound on the size of the non-fd buffer required to
1307 * flatten `FrameEventsDelta`.
1308 *
1309 * \param[in] t The input `FrameEventsDelta`.
1310 * \return A lower bound on the size of the flat buffer.
1311 */
1312constexpr size_t minFlattenedSize(
1313        HGraphicBufferProducer::FrameEventsDelta const& /* t */) {
1314    return sizeof(uint64_t) + // mFrameNumber
1315            sizeof(uint8_t) + // mIndex
1316            sizeof(uint8_t) + // mAddPostCompositeCalled
1317            sizeof(uint8_t) + // mAddRetireCalled
1318            sizeof(uint8_t) + // mAddReleaseCalled
1319            sizeof(nsecs_t) + // mPostedTime
1320            sizeof(nsecs_t) + // mRequestedPresentTime
1321            sizeof(nsecs_t) + // mLatchTime
1322            sizeof(nsecs_t) + // mFirstRefreshStartTime
1323            sizeof(nsecs_t); // mLastRefreshStartTime
1324}
1325
1326/**
1327 * \brief Return the size of the non-fd buffer required to flatten
1328 * `FrameEventsDelta`.
1329 *
1330 * \param[in] t The input `FrameEventsDelta`.
1331 * \return The required size of the flat buffer.
1332 */
1333inline size_t getFlattenedSize(
1334        HGraphicBufferProducer::FrameEventsDelta const& t) {
1335    return minFlattenedSize(t) +
1336            getFlattenedSize(t.gpuCompositionDoneFence) +
1337            getFlattenedSize(t.displayPresentFence) +
1338            getFlattenedSize(t.displayRetireFence) +
1339            getFlattenedSize(t.releaseFence);
1340};
1341
1342/**
1343 * \brief Return the number of file descriptors contained in
1344 * `FrameEventsDelta`.
1345 *
1346 * \param[in] t The input `FrameEventsDelta`.
1347 * \return The number of file descriptors contained in \p t.
1348 */
1349inline size_t getFdCount(
1350        HGraphicBufferProducer::FrameEventsDelta const& t) {
1351    return getFdCount(t.gpuCompositionDoneFence) +
1352            getFdCount(t.displayPresentFence) +
1353            getFdCount(t.displayRetireFence) +
1354            getFdCount(t.releaseFence);
1355};
1356
1357/**
1358 * \brief Unflatten `FrameEventsDelta`.
1359 *
1360 * \param[out] t The destination `FrameEventsDelta`.
1361 * \param[out] nh The underlying array of native handles.
1362 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1363 * \param[in,out] size The size of the flat non-fd buffer.
1364 * \param[in,out] fds The pointer to the flat fd buffer.
1365 * \param[in,out] numFds The size of the flat fd buffer.
1366 * \return `NO_ERROR` on success; other value on failure.
1367 *
1368 * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
1369 * populated with `nullptr` or newly created handles. Each non-null slot in \p
1370 * nh will need to be deleted manually with `native_handle_delete()`.
1371 */
1372inline status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
1373        std::vector<native_handle_t*>* nh,
1374        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1375    if (size < minFlattenedSize(*t)) {
1376        return NO_MEMORY;
1377    }
1378    FlattenableUtils::read(buffer, size, t->frameNumber);
1379
1380    // These were written as uint8_t for alignment.
1381    uint8_t temp = 0;
1382    FlattenableUtils::read(buffer, size, temp);
1383    size_t index = static_cast<size_t>(temp);
1384    if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
1385        return BAD_VALUE;
1386    }
1387    t->index = static_cast<uint32_t>(index);
1388
1389    FlattenableUtils::read(buffer, size, temp);
1390    t->addPostCompositeCalled = static_cast<bool>(temp);
1391    FlattenableUtils::read(buffer, size, temp);
1392    t->addRetireCalled = static_cast<bool>(temp);
1393    FlattenableUtils::read(buffer, size, temp);
1394    t->addReleaseCalled = static_cast<bool>(temp);
1395
1396    FlattenableUtils::read(buffer, size, t->postedTimeNs);
1397    FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
1398    FlattenableUtils::read(buffer, size, t->latchTimeNs);
1399    FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
1400    FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
1401    FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
1402
1403    // Fences
1404    HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
1405    tSnapshot[0] = &t->gpuCompositionDoneFence;
1406    tSnapshot[1] = &t->displayPresentFence;
1407    tSnapshot[2] = &t->displayRetireFence;
1408    tSnapshot[3] = &t->releaseFence;
1409    nh->resize(4);
1410    for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
1411        status_t status = unflatten(
1412                tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
1413                buffer, size, fds, numFds);
1414        if (status != NO_ERROR) {
1415            while (snapshotIndex > 0) {
1416                --snapshotIndex;
1417                if ((*nh)[snapshotIndex] != nullptr) {
1418                    native_handle_delete((*nh)[snapshotIndex]);
1419                }
1420            }
1421            return status;
1422        }
1423    }
1424    return NO_ERROR;
1425}
1426
1427/**
1428 * \brief Flatten `FrameEventsDelta`.
1429 *
1430 * \param[in] t The source `FrameEventsDelta`.
1431 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1432 * \param[in,out] size The size of the flat non-fd buffer.
1433 * \param[in,out] fds The pointer to the flat fd buffer.
1434 * \param[in,out] numFds The size of the flat fd buffer.
1435 * \return `NO_ERROR` on success; other value on failure.
1436 *
1437 * This function will duplicate file descriptors contained in \p t.
1438 */
1439// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
1440//      FrameEventsDelta::flatten
1441inline status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
1442        void*& buffer, size_t& size, int*& fds, size_t numFds) {
1443    // Check that t.index is within a valid range.
1444    if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
1445            || t.index > std::numeric_limits<uint8_t>::max()) {
1446        return BAD_VALUE;
1447    }
1448
1449    FlattenableUtils::write(buffer, size, t.frameNumber);
1450
1451    // These are static_cast to uint8_t for alignment.
1452    FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
1453    FlattenableUtils::write(
1454            buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
1455    FlattenableUtils::write(
1456            buffer, size, static_cast<uint8_t>(t.addRetireCalled));
1457    FlattenableUtils::write(
1458            buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
1459
1460    FlattenableUtils::write(buffer, size, t.postedTimeNs);
1461    FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
1462    FlattenableUtils::write(buffer, size, t.latchTimeNs);
1463    FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
1464    FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
1465    FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
1466
1467    // Fences
1468    HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
1469    tSnapshot[0] = &t.gpuCompositionDoneFence;
1470    tSnapshot[1] = &t.displayPresentFence;
1471    tSnapshot[2] = &t.displayRetireFence;
1472    tSnapshot[3] = &t.releaseFence;
1473    for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
1474        status_t status = flatten(
1475                *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
1476        if (status != NO_ERROR) {
1477            return status;
1478        }
1479    }
1480    return NO_ERROR;
1481}
1482
1483// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
1484
1485/**
1486 * \brief Return the size of the non-fd buffer required to flatten
1487 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
1488 *
1489 * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
1490 * \return The required size of the flat buffer.
1491 */
1492inline size_t getFlattenedSize(
1493        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
1494    size_t size = 4 + // mDeltas.size()
1495            sizeof(t.compositorTiming);
1496    for (size_t i = 0; i < t.deltas.size(); ++i) {
1497        size += getFlattenedSize(t.deltas[i]);
1498    }
1499    return size;
1500}
1501
1502/**
1503 * \brief Return the number of file descriptors contained in
1504 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
1505 *
1506 * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
1507 * \return The number of file descriptors contained in \p t.
1508 */
1509inline size_t getFdCount(
1510        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
1511    size_t numFds = 0;
1512    for (size_t i = 0; i < t.deltas.size(); ++i) {
1513        numFds += getFdCount(t.deltas[i]);
1514    }
1515    return numFds;
1516}
1517
1518/**
1519 * \brief Unflatten `FrameEventHistoryDelta`.
1520 *
1521 * \param[out] t The destination `FrameEventHistoryDelta`.
1522 * \param[out] nh The underlying array of arrays of native handles.
1523 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1524 * \param[in,out] size The size of the flat non-fd buffer.
1525 * \param[in,out] fds The pointer to the flat fd buffer.
1526 * \param[in,out] numFds The size of the flat fd buffer.
1527 * \return `NO_ERROR` on success; other value on failure.
1528 *
1529 * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
1530 * newly created handles. The second dimension of \p nh will be 4. Each non-null
1531 * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
1532 */
1533inline status_t unflatten(
1534        HGraphicBufferProducer::FrameEventHistoryDelta* t,
1535        std::vector<std::vector<native_handle_t*> >* nh,
1536        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1537    if (size < 4) {
1538        return NO_MEMORY;
1539    }
1540
1541    FlattenableUtils::read(buffer, size, t->compositorTiming);
1542
1543    uint32_t deltaCount = 0;
1544    FlattenableUtils::read(buffer, size, deltaCount);
1545    if (static_cast<size_t>(deltaCount) >
1546            ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
1547        return BAD_VALUE;
1548    }
1549    t->deltas.resize(deltaCount);
1550    nh->resize(deltaCount);
1551    for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
1552        status_t status = unflatten(
1553                &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
1554                buffer, size, fds, numFds);
1555        if (status != NO_ERROR) {
1556            return status;
1557        }
1558    }
1559    return NO_ERROR;
1560}
1561
1562/**
1563 * \brief Flatten `FrameEventHistoryDelta`.
1564 *
1565 * \param[in] t The source `FrameEventHistoryDelta`.
1566 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1567 * \param[in,out] size The size of the flat non-fd buffer.
1568 * \param[in,out] fds The pointer to the flat fd buffer.
1569 * \param[in,out] numFds The size of the flat fd buffer.
1570 * \return `NO_ERROR` on success; other value on failure.
1571 *
1572 * This function will duplicate file descriptors contained in \p t.
1573 */
1574inline status_t flatten(
1575        HGraphicBufferProducer::FrameEventHistoryDelta const& t,
1576        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1577    if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
1578        return BAD_VALUE;
1579    }
1580    if (size < getFlattenedSize(t)) {
1581        return NO_MEMORY;
1582    }
1583
1584    FlattenableUtils::write(buffer, size, t.compositorTiming);
1585
1586    FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
1587    for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
1588        status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
1589        if (status != NO_ERROR) {
1590            return status;
1591        }
1592    }
1593    return NO_ERROR;
1594}
1595
1596/**
1597 * \brief Wrap `::android::FrameEventHistoryData` in
1598 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
1599 *
1600 * \param[out] t The wrapper of type
1601 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
1602 * \param[out] nh The array of array of native handles that are referred to by
1603 * members of \p t.
1604 * \param[in] l The source `::android::FrameEventHistoryDelta`.
1605 *
1606 * On success, each member of \p nh will be either `nullptr` or a newly created
1607 * native handle. All the non-`nullptr` elements must be deleted individually
1608 * with `native_handle_delete()`.
1609 */
1610inline bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
1611        std::vector<std::vector<native_handle_t*> >* nh,
1612        ::android::FrameEventHistoryDelta const& l) {
1613
1614    size_t const baseSize = l.getFlattenedSize();
1615    std::unique_ptr<uint8_t[]> baseBuffer(
1616            new (std::nothrow) uint8_t[baseSize]);
1617    if (!baseBuffer) {
1618        return false;
1619    }
1620
1621    size_t const baseNumFds = l.getFdCount();
1622    std::unique_ptr<int[]> baseFds(
1623            new (std::nothrow) int[baseNumFds]);
1624    if (!baseFds) {
1625        return false;
1626    }
1627
1628    void* buffer = static_cast<void*>(baseBuffer.get());
1629    size_t size = baseSize;
1630    int* fds = baseFds.get();
1631    size_t numFds = baseNumFds;
1632    if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
1633        return false;
1634    }
1635
1636    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1637    size = baseSize;
1638    int const* constFds = static_cast<int const*>(baseFds.get());
1639    numFds = baseNumFds;
1640    if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
1641        return false;
1642    }
1643
1644    return true;
1645}
1646
1647/**
1648 * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
1649 * `::android::FrameEventHistoryDelta`.
1650 *
1651 * \param[out] l The destination `::android::FrameEventHistoryDelta`.
1652 * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
1653 *
1654 * This function will duplicate all file descriptors contained in \p t.
1655 */
1656inline bool convertTo(
1657        ::android::FrameEventHistoryDelta* l,
1658        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
1659
1660    size_t const baseSize = getFlattenedSize(t);
1661    std::unique_ptr<uint8_t[]> baseBuffer(
1662            new (std::nothrow) uint8_t[baseSize]);
1663    if (!baseBuffer) {
1664        return false;
1665    }
1666
1667    size_t const baseNumFds = getFdCount(t);
1668    std::unique_ptr<int[]> baseFds(
1669            new (std::nothrow) int[baseNumFds]);
1670    if (!baseFds) {
1671        return false;
1672    }
1673
1674    void* buffer = static_cast<void*>(baseBuffer.get());
1675    size_t size = baseSize;
1676    int* fds = static_cast<int*>(baseFds.get());
1677    size_t numFds = baseNumFds;
1678    if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
1679        return false;
1680    }
1681
1682    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1683    size = baseSize;
1684    int const* constFds = static_cast<int const*>(baseFds.get());
1685    numFds = baseNumFds;
1686    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
1687        return false;
1688    }
1689
1690    return true;
1691}
1692
1693// Ref: frameworks/native/libs/ui/Region.cpp
1694
1695/**
1696 * \brief Return the size of the buffer required to flatten `Region`.
1697 *
1698 * \param[in] t The input `Region`.
1699 * \return The required size of the flat buffer.
1700 */
1701inline size_t getFlattenedSize(Region const& t) {
1702    return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
1703}
1704
1705/**
1706 * \brief Unflatten `Region`.
1707 *
1708 * \param[out] t The destination `Region`.
1709 * \param[in,out] buffer The pointer to the flat buffer.
1710 * \param[in,out] size The size of the flat buffer.
1711 * \return `NO_ERROR` on success; other value on failure.
1712 */
1713inline status_t unflatten(Region* t, void const*& buffer, size_t& size) {
1714    if (size < sizeof(uint32_t)) {
1715        return NO_MEMORY;
1716    }
1717
1718    uint32_t numRects = 0;
1719    FlattenableUtils::read(buffer, size, numRects);
1720    if (size < numRects * sizeof(Rect)) {
1721        return NO_MEMORY;
1722    }
1723    if (numRects > (UINT32_MAX / sizeof(Rect))) {
1724        return NO_MEMORY;
1725    }
1726
1727    t->resize(numRects);
1728    for (size_t r = 0; r < numRects; ++r) {
1729        ::android::Rect rect(::android::Rect::EMPTY_RECT);
1730        status_t status = rect.unflatten(buffer, size);
1731        if (status != NO_ERROR) {
1732            return status;
1733        }
1734        FlattenableUtils::advance(buffer, size, sizeof(rect));
1735        (*t)[r] = Rect{
1736                static_cast<int32_t>(rect.left),
1737                static_cast<int32_t>(rect.top),
1738                static_cast<int32_t>(rect.right),
1739                static_cast<int32_t>(rect.bottom)};
1740    }
1741    return NO_ERROR;
1742}
1743
1744/**
1745 * \brief Flatten `Region`.
1746 *
1747 * \param[in] t The source `Region`.
1748 * \param[in,out] buffer The pointer to the flat buffer.
1749 * \param[in,out] size The size of the flat buffer.
1750 * \return `NO_ERROR` on success; other value on failure.
1751 */
1752inline status_t flatten(Region const& t, void*& buffer, size_t& size) {
1753    if (size < getFlattenedSize(t)) {
1754        return NO_MEMORY;
1755    }
1756
1757    FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
1758    for (size_t r = 0; r < t.size(); ++r) {
1759        ::android::Rect rect(
1760                static_cast<int32_t>(t[r].left),
1761                static_cast<int32_t>(t[r].top),
1762                static_cast<int32_t>(t[r].right),
1763                static_cast<int32_t>(t[r].bottom));
1764        status_t status = rect.flatten(buffer, size);
1765        if (status != NO_ERROR) {
1766            return status;
1767        }
1768        FlattenableUtils::advance(buffer, size, sizeof(rect));
1769    }
1770    return NO_ERROR;
1771}
1772
1773/**
1774 * \brief Convert `::android::Region` to `Region`.
1775 *
1776 * \param[out] t The destination `Region`.
1777 * \param[in] l The source `::android::Region`.
1778 */
1779// convert: ::android::Region -> Region
1780inline bool convertTo(Region* t, ::android::Region const& l) {
1781    size_t const baseSize = l.getFlattenedSize();
1782    std::unique_ptr<uint8_t[]> baseBuffer(
1783            new (std::nothrow) uint8_t[baseSize]);
1784    if (!baseBuffer) {
1785        return false;
1786    }
1787
1788    void* buffer = static_cast<void*>(baseBuffer.get());
1789    size_t size = baseSize;
1790    if (l.flatten(buffer, size) != NO_ERROR) {
1791        return false;
1792    }
1793
1794    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1795    size = baseSize;
1796    if (unflatten(t, constBuffer, size) != NO_ERROR) {
1797        return false;
1798    }
1799
1800    return true;
1801}
1802
1803/**
1804 * \brief Convert `Region` to `::android::Region`.
1805 *
1806 * \param[out] l The destination `::android::Region`.
1807 * \param[in] t The source `Region`.
1808 */
1809// convert: Region -> ::android::Region
1810inline bool convertTo(::android::Region* l, Region const& t) {
1811    size_t const baseSize = getFlattenedSize(t);
1812    std::unique_ptr<uint8_t[]> baseBuffer(
1813            new (std::nothrow) uint8_t[baseSize]);
1814    if (!baseBuffer) {
1815        return false;
1816    }
1817
1818    void* buffer = static_cast<void*>(baseBuffer.get());
1819    size_t size = baseSize;
1820    if (flatten(t, buffer, size) != NO_ERROR) {
1821        return false;
1822    }
1823
1824    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1825    size = baseSize;
1826    if (l->unflatten(constBuffer, size) != NO_ERROR) {
1827        return false;
1828    }
1829
1830    return true;
1831}
1832
1833// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
1834//      BGraphicBufferProducer::QueueBufferInput
1835
1836/**
1837 * \brief Return a lower bound on the size of the buffer required to flatten
1838 * `HGraphicBufferProducer::QueueBufferInput`.
1839 *
1840 * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
1841 * \return A lower bound on the size of the flat buffer.
1842 */
1843constexpr size_t minFlattenedSize(
1844        HGraphicBufferProducer::QueueBufferInput const& /* t */) {
1845    return sizeof(int64_t) + // timestamp
1846            sizeof(int) + // isAutoTimestamp
1847            sizeof(android_dataspace) + // dataSpace
1848            sizeof(::android::Rect) + // crop
1849            sizeof(int) + // scalingMode
1850            sizeof(uint32_t) + // transform
1851            sizeof(uint32_t) + // stickyTransform
1852            sizeof(bool); // getFrameTimestamps
1853}
1854
1855/**
1856 * \brief Return the size of the buffer required to flatten
1857 * `HGraphicBufferProducer::QueueBufferInput`.
1858 *
1859 * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
1860 * \return The required size of the flat buffer.
1861 */
1862inline size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
1863    return minFlattenedSize(t) +
1864            getFenceFlattenedSize(t.fence) +
1865            getFlattenedSize(t.surfaceDamage) +
1866            sizeof(HdrMetadata::validTypes);
1867}
1868
1869/**
1870 * \brief Return the number of file descriptors contained in
1871 * `HGraphicBufferProducer::QueueBufferInput`.
1872 *
1873 * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
1874 * \return The number of file descriptors contained in \p t.
1875 */
1876inline size_t getFdCount(
1877        HGraphicBufferProducer::QueueBufferInput const& t) {
1878    return getFenceFdCount(t.fence);
1879}
1880
1881/**
1882 * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
1883 *
1884 * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
1885 * \param[out] nh The native handle cloned from `t.fence`.
1886 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1887 * \param[in,out] size The size of the flat non-fd buffer.
1888 * \param[in,out] fds The pointer to the flat fd buffer.
1889 * \param[in,out] numFds The size of the flat fd buffer.
1890 * \return `NO_ERROR` on success; other value on failure.
1891 *
1892 * This function will duplicate the file descriptor in `t.fence`. */
1893inline status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
1894        native_handle_t** nh,
1895        void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1896    if (size < getFlattenedSize(t)) {
1897        return NO_MEMORY;
1898    }
1899
1900    FlattenableUtils::write(buffer, size, t.timestamp);
1901    FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
1902    FlattenableUtils::write(buffer, size,
1903            static_cast<android_dataspace_t>(t.dataSpace));
1904    FlattenableUtils::write(buffer, size, ::android::Rect(
1905            static_cast<int32_t>(t.crop.left),
1906            static_cast<int32_t>(t.crop.top),
1907            static_cast<int32_t>(t.crop.right),
1908            static_cast<int32_t>(t.crop.bottom)));
1909    FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
1910    FlattenableUtils::write(buffer, size, t.transform);
1911    FlattenableUtils::write(buffer, size, t.stickyTransform);
1912    FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
1913
1914    *nh = t.fence.getNativeHandle() == nullptr ?
1915            nullptr : native_handle_clone(t.fence);
1916    status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
1917    if (status != NO_ERROR) {
1918        return status;
1919    }
1920    status = flatten(t.surfaceDamage, buffer, size);
1921    if (status != NO_ERROR) {
1922        return status;
1923    }
1924    FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
1925    return NO_ERROR;
1926}
1927
1928/**
1929 * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
1930 *
1931 * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
1932 * \param[out] nh The underlying native handle for `t->fence`.
1933 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1934 * \param[in,out] size The size of the flat non-fd buffer.
1935 * \param[in,out] fds The pointer to the flat fd buffer.
1936 * \param[in,out] numFds The size of the flat fd buffer.
1937 * \return `NO_ERROR` on success; other value on failure.
1938 *
1939 * If the return value is `NO_ERROR` and `t->fence` contains a valid file
1940 * descriptor, \p nh will be a newly created native handle holding that file
1941 * descriptor. \p nh needs to be deleted with `native_handle_delete()`
1942 * afterwards.
1943 */
1944inline status_t unflatten(
1945        HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
1946        void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1947    if (size < minFlattenedSize(*t)) {
1948        return NO_MEMORY;
1949    }
1950
1951    FlattenableUtils::read(buffer, size, t->timestamp);
1952    int lIsAutoTimestamp;
1953    FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
1954    t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
1955    android_dataspace_t lDataSpace;
1956    FlattenableUtils::read(buffer, size, lDataSpace);
1957    t->dataSpace = static_cast<Dataspace>(lDataSpace);
1958    Rect lCrop;
1959    FlattenableUtils::read(buffer, size, lCrop);
1960    t->crop = Rect{
1961            static_cast<int32_t>(lCrop.left),
1962            static_cast<int32_t>(lCrop.top),
1963            static_cast<int32_t>(lCrop.right),
1964            static_cast<int32_t>(lCrop.bottom)};
1965    int lScalingMode;
1966    FlattenableUtils::read(buffer, size, lScalingMode);
1967    t->scalingMode = static_cast<int32_t>(lScalingMode);
1968    FlattenableUtils::read(buffer, size, t->transform);
1969    FlattenableUtils::read(buffer, size, t->stickyTransform);
1970    FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
1971
1972    status_t status = unflattenFence(&(t->fence), nh,
1973            buffer, size, fds, numFds);
1974    if (status != NO_ERROR) {
1975        return status;
1976    }
1977    // HdrMetadata ignored
1978    return unflatten(&(t->surfaceDamage), buffer, size);
1979}
1980
1981/**
1982 * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
1983 * `HGraphicBufferProducer::QueueBufferInput`.
1984 *
1985 * \param[out] t The wrapper of type
1986 * `HGraphicBufferProducer::QueueBufferInput`.
1987 * \param[out] nh The underlying native handle for `t->fence`.
1988 * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
1989 *
1990 * If the return value is `true` and `t->fence` contains a valid file
1991 * descriptor, \p nh will be a newly created native handle holding that file
1992 * descriptor. \p nh needs to be deleted with `native_handle_delete()`
1993 * afterwards.
1994 */
1995inline bool wrapAs(
1996        HGraphicBufferProducer::QueueBufferInput* t,
1997        native_handle_t** nh,
1998        BGraphicBufferProducer::QueueBufferInput const& l) {
1999
2000    size_t const baseSize = l.getFlattenedSize();
2001    std::unique_ptr<uint8_t[]> baseBuffer(
2002            new (std::nothrow) uint8_t[baseSize]);
2003    if (!baseBuffer) {
2004        return false;
2005    }
2006
2007    size_t const baseNumFds = l.getFdCount();
2008    std::unique_ptr<int[]> baseFds(
2009            new (std::nothrow) int[baseNumFds]);
2010    if (!baseFds) {
2011        return false;
2012    }
2013
2014    void* buffer = static_cast<void*>(baseBuffer.get());
2015    size_t size = baseSize;
2016    int* fds = baseFds.get();
2017    size_t numFds = baseNumFds;
2018    if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
2019        return false;
2020    }
2021
2022    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
2023    size = baseSize;
2024    int const* constFds = static_cast<int const*>(baseFds.get());
2025    numFds = baseNumFds;
2026    if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
2027        return false;
2028    }
2029
2030    return true;
2031}
2032
2033/**
2034 * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
2035 * `BGraphicBufferProducer::QueueBufferInput`.
2036 *
2037 * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
2038 * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
2039 *
2040 * If `t.fence` has a valid file descriptor, it will be duplicated.
2041 */
2042inline bool convertTo(
2043        BGraphicBufferProducer::QueueBufferInput* l,
2044        HGraphicBufferProducer::QueueBufferInput const& t) {
2045
2046    size_t const baseSize = getFlattenedSize(t);
2047    std::unique_ptr<uint8_t[]> baseBuffer(
2048            new (std::nothrow) uint8_t[baseSize]);
2049    if (!baseBuffer) {
2050        return false;
2051    }
2052
2053    size_t const baseNumFds = getFdCount(t);
2054    std::unique_ptr<int[]> baseFds(
2055            new (std::nothrow) int[baseNumFds]);
2056    if (!baseFds) {
2057        return false;
2058    }
2059
2060    void* buffer = static_cast<void*>(baseBuffer.get());
2061    size_t size = baseSize;
2062    int* fds = baseFds.get();
2063    size_t numFds = baseNumFds;
2064    native_handle_t* nh;
2065    if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
2066        return false;
2067    }
2068
2069    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
2070    size = baseSize;
2071    int const* constFds = static_cast<int const*>(baseFds.get());
2072    numFds = baseNumFds;
2073    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
2074        if (nh != nullptr) {
2075            native_handle_close(nh);
2076            native_handle_delete(nh);
2077        }
2078        return false;
2079    }
2080
2081    native_handle_delete(nh);
2082    return true;
2083}
2084
2085// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
2086//      BGraphicBufferProducer::QueueBufferOutput
2087
2088/**
2089 * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
2090 * `HGraphicBufferProducer::QueueBufferOutput`.
2091 *
2092 * \param[out] t The wrapper of type
2093 * `HGraphicBufferProducer::QueueBufferOutput`.
2094 * \param[out] nh The array of array of native handles that are referred to by
2095 * members of \p t.
2096 * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
2097 *
2098 * On success, each member of \p nh will be either `nullptr` or a newly created
2099 * native handle. All the non-`nullptr` elements must be deleted individually
2100 * with `native_handle_delete()`.
2101 */
2102// wrap: BGraphicBufferProducer::QueueBufferOutput ->
2103// HGraphicBufferProducer::QueueBufferOutput
2104inline bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
2105        std::vector<std::vector<native_handle_t*> >* nh,
2106        BGraphicBufferProducer::QueueBufferOutput const& l) {
2107    if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
2108        return false;
2109    }
2110    t->width = l.width;
2111    t->height = l.height;
2112    t->transformHint = l.transformHint;
2113    t->numPendingBuffers = l.numPendingBuffers;
2114    t->nextFrameNumber = l.nextFrameNumber;
2115    t->bufferReplaced = l.bufferReplaced;
2116    return true;
2117}
2118
2119/**
2120 * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
2121 * `BGraphicBufferProducer::QueueBufferOutput`.
2122 *
2123 * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
2124 * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
2125 *
2126 * This function will duplicate all file descriptors contained in \p t.
2127 */
2128// convert: HGraphicBufferProducer::QueueBufferOutput ->
2129// BGraphicBufferProducer::QueueBufferOutput
2130inline bool convertTo(
2131        BGraphicBufferProducer::QueueBufferOutput* l,
2132        HGraphicBufferProducer::QueueBufferOutput const& t) {
2133    if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
2134        return false;
2135    }
2136    l->width = t.width;
2137    l->height = t.height;
2138    l->transformHint = t.transformHint;
2139    l->numPendingBuffers = t.numPendingBuffers;
2140    l->nextFrameNumber = t.nextFrameNumber;
2141    l->bufferReplaced = t.bufferReplaced;
2142    return true;
2143}
2144
2145/**
2146 * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
2147 * `HGraphicBufferProducer::DisconnectMode`.
2148 *
2149 * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
2150 * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
2151 */
2152inline HGraphicBufferProducer::DisconnectMode toOmxDisconnectMode(
2153        BGraphicBufferProducer::DisconnectMode l) {
2154    switch (l) {
2155        case BGraphicBufferProducer::DisconnectMode::Api:
2156            return HGraphicBufferProducer::DisconnectMode::API;
2157        case BGraphicBufferProducer::DisconnectMode::AllLocal:
2158            return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
2159    }
2160    return HGraphicBufferProducer::DisconnectMode::API;
2161}
2162
2163/**
2164 * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
2165 * `BGraphicBufferProducer::DisconnectMode`.
2166 *
2167 * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
2168 * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
2169 */
2170inline BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
2171        HGraphicBufferProducer::DisconnectMode t) {
2172    switch (t) {
2173        case HGraphicBufferProducer::DisconnectMode::API:
2174            return BGraphicBufferProducer::DisconnectMode::Api;
2175        case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
2176            return BGraphicBufferProducer::DisconnectMode::AllLocal;
2177    }
2178    return BGraphicBufferProducer::DisconnectMode::Api;
2179}
2180
2181}  // namespace implementation
2182}  // namespace V1_0
2183}  // namespace omx
2184}  // namespace media
2185}  // namespace hardware
2186}  // namespace android
2187
2188#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
2189