Home | History | Annotate | Download | only in bqhelper
      1 /*
      2  * Copyright 2018, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <media/stagefright/bqhelper/Conversion.h>
     18 
     19 namespace android {
     20 namespace conversion {
     21 
     22 // native_handle_t helper functions.
     23 
     24 /**
     25  * \brief Take an fd and create a native handle containing only the given fd.
     26  * The created handle will need to be deleted manually with
     27  * `native_handle_delete()`.
     28  *
     29  * \param[in] fd The source file descriptor (of type `int`).
     30  * \return The create `native_handle_t*` that contains the given \p fd. If the
     31  * supplied \p fd is negative, the created native handle will contain no file
     32  * descriptors.
     33  *
     34  * If the native handle cannot be created, the return value will be
     35  * `nullptr`.
     36  *
     37  * This function does not duplicate the file descriptor.
     38  */
     39 native_handle_t* native_handle_create_from_fd(int fd) {
     40     if (fd < 2) {
     41         return native_handle_create(0, 0);
     42     }
     43     native_handle_t* nh = native_handle_create(1, 0);
     44     if (nh == nullptr) {
     45         return nullptr;
     46     }
     47     nh->data[0] = fd;
     48     return nh;
     49 }
     50 
     51 /**
     52  * \brief Extract a file descriptor from a native handle.
     53  *
     54  * \param[in] nh The source `native_handle_t*`.
     55  * \param[in] index The index of the file descriptor in \p nh to read from. This
     56  * input has the default value of `0`.
     57  * \return The `index`-th file descriptor in \p nh. If \p nh does not have
     58  * enough file descriptors, the returned value will be `-1`.
     59  *
     60  * This function does not duplicate the file descriptor.
     61  */
     62 int native_handle_read_fd(native_handle_t const* nh, int index) {
     63     return ((nh == nullptr) || (nh->numFds == 0) ||
     64             (nh->numFds <= index) || (index < 0)) ?
     65             -1 : nh->data[index];
     66 }
     67 
     68 /**
     69  * Conversion functions
     70  * ====================
     71  *
     72  * There are two main directions of conversion:
     73  * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
     74  *   input. The wrapper has type `TargetType`.
     75  * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
     76  *   corresponds to the input. The lifetime of the output does not depend on the
     77  *   lifetime of the input.
     78  * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
     79  *   that cannot be copied and/or moved efficiently, or when there are multiple
     80  *   output arguments.
     81  * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
     82  *   `TargetType` that cannot be copied and/or moved efficiently, or when there
     83  *   are multiple output arguments.
     84  *
     85  * `wrapIn()` and `convertTo()` functions will take output arguments before
     86  * input arguments. Some of these functions might return a value to indicate
     87  * success or error.
     88  *
     89  * In converting or wrapping something as a Treble type that contains a
     90  * `hidl_handle`, `native_handle_t*` will need to be created and returned as
     91  * an additional output argument, hence only `wrapIn()` or `convertTo()` would
     92  * be available. The caller must call `native_handle_delete()` to deallocate the
     93  * returned native handle when it is no longer needed.
     94  *
     95  * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
     96  * not perform duplication of file descriptors, while `toTargetType()` and
     97  * `convertTo()` do.
     98  */
     99 
    100 /**
    101  * \brief Convert `Return<void>` to `binder::Status`.
    102  *
    103  * \param[in] t The source `Return<void>`.
    104  * \return The corresponding `binder::Status`.
    105  */
    106 // convert: Return<void> -> ::android::binder::Status
    107 ::android::binder::Status toBinderStatus(
    108         Return<void> const& t) {
    109     return ::android::binder::Status::fromExceptionCode(
    110             t.isOk() ? OK : UNKNOWN_ERROR,
    111             t.description().c_str());
    112 }
    113 
    114 /**
    115  * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
    116  *
    117  * \param[in] t The source `Return<void>`.
    118  * \return The corresponding `status_t`.
    119  */
    120 // convert: Return<void> -> status_t
    121 status_t toStatusT(Return<void> const& t) {
    122     return t.isOk() ? OK : UNKNOWN_ERROR;
    123 }
    124 
    125 /**
    126  * \brief Wrap `native_handle_t*` in `hidl_handle`.
    127  *
    128  * \param[in] nh The source `native_handle_t*`.
    129  * \return The `hidl_handle` that points to \p nh.
    130  */
    131 // wrap: native_handle_t* -> hidl_handle
    132 hidl_handle inHidlHandle(native_handle_t const* nh) {
    133     return hidl_handle(nh);
    134 }
    135 
    136 /**
    137  * \brief Convert `int32_t` to `Dataspace`.
    138  *
    139  * \param[in] l The source `int32_t`.
    140  * \result The corresponding `Dataspace`.
    141  */
    142 // convert: int32_t -> Dataspace
    143 Dataspace toHardwareDataspace(int32_t l) {
    144     return static_cast<Dataspace>(l);
    145 }
    146 
    147 /**
    148  * \brief Convert `Dataspace` to `int32_t`.
    149  *
    150  * \param[in] t The source `Dataspace`.
    151  * \result The corresponding `int32_t`.
    152  */
    153 // convert: Dataspace -> int32_t
    154 int32_t toRawDataspace(Dataspace const& t) {
    155     return static_cast<int32_t>(t);
    156 }
    157 
    158 /**
    159  * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
    160  *
    161  * \param[in] l The pointer to the beginning of the opaque buffer.
    162  * \param[in] size The size of the buffer.
    163  * \return A `hidl_vec<uint8_t>` that points to the buffer.
    164  */
    165 // wrap: void*, size_t -> hidl_vec<uint8_t>
    166 hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
    167     hidl_vec<uint8_t> t;
    168     t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
    169     return t;
    170 }
    171 
    172 /**
    173  * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
    174  *
    175  * \param[in] l The pointer to the beginning of the opaque buffer.
    176  * \param[in] size The size of the buffer.
    177  * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
    178  */
    179 // convert: void*, size_t -> hidl_vec<uint8_t>
    180 hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
    181     hidl_vec<uint8_t> t;
    182     t.resize(size);
    183     uint8_t const* src = static_cast<uint8_t const*>(l);
    184     std::copy(src, src + size, t.data());
    185     return t;
    186 }
    187 
    188 /**
    189  * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
    190  *
    191  * \param[out] t The wrapper of type `AnwBuffer`.
    192  * \param[in] l The source `GraphicBuffer`.
    193  */
    194 // wrap: GraphicBuffer -> AnwBuffer
    195 void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
    196     t->attr.width = l.getWidth();
    197     t->attr.height = l.getHeight();
    198     t->attr.stride = l.getStride();
    199     t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
    200     t->attr.layerCount = l.getLayerCount();
    201     t->attr.usage = l.getUsage();
    202     t->attr.id = l.getId();
    203     t->attr.generationNumber = l.getGenerationNumber();
    204     t->nativeHandle = hidl_handle(l.handle);
    205 }
    206 
    207 /**
    208  * \brief Convert `AnwBuffer` to `GraphicBuffer`.
    209  *
    210  * \param[out] l The destination `GraphicBuffer`.
    211  * \param[in] t The source `AnwBuffer`.
    212  *
    213  * This function will duplicate all file descriptors in \p t.
    214  */
    215 // convert: AnwBuffer -> GraphicBuffer
    216 // Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
    217 bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
    218     native_handle_t* handle = t.nativeHandle == nullptr ?
    219             nullptr : native_handle_clone(t.nativeHandle);
    220 
    221     size_t const numInts = 12 + (handle ? handle->numInts : 0);
    222     int32_t* ints = new int32_t[numInts];
    223 
    224     size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
    225     int* fds = new int[numFds];
    226 
    227     ints[0] = 'GBFR';
    228     ints[1] = static_cast<int32_t>(t.attr.width);
    229     ints[2] = static_cast<int32_t>(t.attr.height);
    230     ints[3] = static_cast<int32_t>(t.attr.stride);
    231     ints[4] = static_cast<int32_t>(t.attr.format);
    232     ints[5] = static_cast<int32_t>(t.attr.layerCount);
    233     ints[6] = static_cast<int32_t>(t.attr.usage);
    234     ints[7] = static_cast<int32_t>(t.attr.id >> 32);
    235     ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
    236     ints[9] = static_cast<int32_t>(t.attr.generationNumber);
    237     ints[10] = 0;
    238     ints[11] = 0;
    239     if (handle) {
    240         ints[10] = static_cast<int32_t>(handle->numFds);
    241         ints[11] = static_cast<int32_t>(handle->numInts);
    242         int* intsStart = handle->data + handle->numFds;
    243         std::copy(handle->data, intsStart, fds);
    244         std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
    245     }
    246 
    247     void const* constBuffer = static_cast<void const*>(ints);
    248     size_t size = numInts * sizeof(int32_t);
    249     int const* constFds = static_cast<int const*>(fds);
    250     status_t status = l->unflatten(constBuffer, size, constFds, numFds);
    251 
    252     delete [] fds;
    253     delete [] ints;
    254     native_handle_delete(handle);
    255     return status == NO_ERROR;
    256 }
    257 
    258 /**
    259  * Conversion functions for types outside media
    260  * ============================================
    261  *
    262  * Some objects in libui and libgui that were made to go through binder calls do
    263  * not expose ways to read or write their fields to the public. To pass an
    264  * object of this kind through the HIDL boundary, translation functions need to
    265  * work around the access restriction by using the publicly available
    266  * `flatten()` and `unflatten()` functions.
    267  *
    268  * All `flatten()` and `unflatten()` overloads follow the same convention as
    269  * follows:
    270  *
    271  *     status_t flatten(ObjectType const& object,
    272  *                      [OtherType const& other, ...]
    273  *                      void*& buffer, size_t& size,
    274  *                      int*& fds, size_t& numFds)
    275  *
    276  *     status_t unflatten(ObjectType* object,
    277  *                        [OtherType* other, ...,]
    278  *                        void*& buffer, size_t& size,
    279  *                        int*& fds, size_t& numFds)
    280  *
    281  * The number of `other` parameters varies depending on the `ObjectType`. For
    282  * example, in the process of unflattening an object that contains
    283  * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
    284  * be created.
    285  *
    286  * The last four parameters always work the same way in all overloads of
    287  * `flatten()` and `unflatten()`:
    288  * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
    289  *   `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
    290  *   `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
    291  *   size (in ints) of the fd buffer pointed to by `fds`.
    292  * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
    293  *   from, `size` is the size (in bytes) of the non-fd buffer pointed to by
    294  *   `buffer`, `fds` is the pointer to the fd buffer to be read from, and
    295  *   `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
    296  * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
    297  *   will be advanced, while `size` and `numFds` will be decreased to reflect
    298  *   how much storage/data of the two buffers (fd and non-fd) have been used.
    299  * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
    300  *   `numFds` are invalid.
    301  *
    302  * The return value of a successful `flatten()` or `unflatten()` call will be
    303  * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
    304  *
    305  * For each object type that supports flattening, there will be two accompanying
    306  * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
    307  * return the size of the non-fd buffer that the object will need for
    308  * flattening. `getFdCount()` will return the size of the fd buffer that the
    309  * object will need for flattening.
    310  *
    311  * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
    312  * `flatten()` and `unflatten()`, are similar to functions of the same name in
    313  * the abstract class `Flattenable`. The only difference is that functions in
    314  * this file are not member functions of the object type. For example, we write
    315  *
    316  *     flatten(x, buffer, size, fds, numFds)
    317  *
    318  * instead of
    319  *
    320  *     x.flatten(buffer, size, fds, numFds)
    321  *
    322  * because we cannot modify the type of `x`.
    323  *
    324  * There is one exception to the naming convention: `hidl_handle` that
    325  * represents a fence. The four functions for this "Fence" type have the word
    326  * "Fence" attched to their names because the object type, which is
    327  * `hidl_handle`, does not carry the special meaning that the object itself can
    328  * only contain zero or one file descriptor.
    329  */
    330 
    331 // Ref: frameworks/native/libs/ui/Fence.cpp
    332 
    333 /**
    334  * \brief Return the size of the non-fd buffer required to flatten a fence.
    335  *
    336  * \param[in] fence The input fence of type `hidl_handle`.
    337  * \return The required size of the flat buffer.
    338  *
    339  * The current version of this function always returns 4, which is the number of
    340  * bytes required to store the number of file descriptors contained in the fd
    341  * part of the flat buffer.
    342  */
    343 size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
    344     return 4;
    345 };
    346 
    347 /**
    348  * \brief Return the number of file descriptors contained in a fence.
    349  *
    350  * \param[in] fence The input fence of type `hidl_handle`.
    351  * \return `0` if \p fence does not contain a valid file descriptor, or `1`
    352  * otherwise.
    353  */
    354 size_t getFenceFdCount(hidl_handle const& fence) {
    355     return native_handle_read_fd(fence) == -1 ? 0 : 1;
    356 }
    357 
    358 /**
    359  * \brief Unflatten `Fence` to `hidl_handle`.
    360  *
    361  * \param[out] fence The destination `hidl_handle`.
    362  * \param[out] nh The underlying native handle.
    363  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    364  * \param[in,out] size The size of the flat non-fd buffer.
    365  * \param[in,out] fds The pointer to the flat fd buffer.
    366  * \param[in,out] numFds The size of the flat fd buffer.
    367  * \return `NO_ERROR` on success; other value on failure.
    368  *
    369  * If the return value is `NO_ERROR`, \p nh will point to a newly created
    370  * native handle, which needs to be deleted with `native_handle_delete()`
    371  * afterwards.
    372  */
    373 status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
    374         void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
    375     if (size < 4) {
    376         return NO_MEMORY;
    377     }
    378 
    379     uint32_t numFdsInHandle;
    380     FlattenableUtils::read(buffer, size, numFdsInHandle);
    381 
    382     if (numFdsInHandle > 1) {
    383         return BAD_VALUE;
    384     }
    385 
    386     if (numFds < numFdsInHandle) {
    387         return NO_MEMORY;
    388     }
    389 
    390     if (numFdsInHandle) {
    391         *nh = native_handle_create_from_fd(*fds);
    392         if (*nh == nullptr) {
    393             return NO_MEMORY;
    394         }
    395         *fence = *nh;
    396         ++fds;
    397         --numFds;
    398     } else {
    399         *nh = nullptr;
    400         *fence = hidl_handle();
    401     }
    402 
    403     return NO_ERROR;
    404 }
    405 
    406 /**
    407  * \brief Flatten `hidl_handle` as `Fence`.
    408  *
    409  * \param[in] t The source `hidl_handle`.
    410  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    411  * \param[in,out] size The size of the flat non-fd buffer.
    412  * \param[in,out] fds The pointer to the flat fd buffer.
    413  * \param[in,out] numFds The size of the flat fd buffer.
    414  * \return `NO_ERROR` on success; other value on failure.
    415  */
    416 status_t flattenFence(hidl_handle const& fence,
    417         void*& buffer, size_t& size, int*& fds, size_t& numFds) {
    418     if (size < getFenceFlattenedSize(fence) ||
    419             numFds < getFenceFdCount(fence)) {
    420         return NO_MEMORY;
    421     }
    422     // Cast to uint32_t since the size of a size_t can vary between 32- and
    423     // 64-bit processes
    424     FlattenableUtils::write(buffer, size,
    425             static_cast<uint32_t>(getFenceFdCount(fence)));
    426     int fd = native_handle_read_fd(fence);
    427     if (fd != -1) {
    428         *fds = fd;
    429         ++fds;
    430         --numFds;
    431     }
    432     return NO_ERROR;
    433 }
    434 
    435 /**
    436  * \brief Wrap `Fence` in `hidl_handle`.
    437  *
    438  * \param[out] t The wrapper of type `hidl_handle`.
    439  * \param[out] nh The native handle pointed to by \p t.
    440  * \param[in] l The source `Fence`.
    441  *
    442  * On success, \p nh will hold a newly created native handle, which must be
    443  * deleted manually with `native_handle_delete()` afterwards.
    444  */
    445 // wrap: Fence -> hidl_handle
    446 bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
    447     size_t const baseSize = l.getFlattenedSize();
    448     std::unique_ptr<uint8_t[]> baseBuffer(
    449             new (std::nothrow) uint8_t[baseSize]);
    450     if (!baseBuffer) {
    451         return false;
    452     }
    453 
    454     size_t const baseNumFds = l.getFdCount();
    455     std::unique_ptr<int[]> baseFds(
    456             new (std::nothrow) int[baseNumFds]);
    457     if (!baseFds) {
    458         return false;
    459     }
    460 
    461     void* buffer = static_cast<void*>(baseBuffer.get());
    462     size_t size = baseSize;
    463     int* fds = static_cast<int*>(baseFds.get());
    464     size_t numFds = baseNumFds;
    465     if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
    466         return false;
    467     }
    468 
    469     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
    470     size = baseSize;
    471     int const* constFds = static_cast<int const*>(baseFds.get());
    472     numFds = baseNumFds;
    473     if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
    474             != NO_ERROR) {
    475         return false;
    476     }
    477 
    478     return true;
    479 }
    480 
    481 /**
    482  * \brief Convert `hidl_handle` to `Fence`.
    483  *
    484  * \param[out] l The destination `Fence`. `l` must not have been used
    485  * (`l->isValid()` must return `false`) before this function is called.
    486  * \param[in] t The source `hidl_handle`.
    487  *
    488  * If \p t contains a valid file descriptor, it will be duplicated.
    489  */
    490 // convert: hidl_handle -> Fence
    491 bool convertTo(Fence* l, hidl_handle const& t) {
    492     int fd = native_handle_read_fd(t);
    493     if (fd != -1) {
    494         fd = dup(fd);
    495         if (fd == -1) {
    496             return false;
    497         }
    498     }
    499     native_handle_t* nh = native_handle_create_from_fd(fd);
    500     if (nh == nullptr) {
    501         if (fd != -1) {
    502             close(fd);
    503         }
    504         return false;
    505     }
    506 
    507     size_t const baseSize = getFenceFlattenedSize(t);
    508     std::unique_ptr<uint8_t[]> baseBuffer(
    509             new (std::nothrow) uint8_t[baseSize]);
    510     if (!baseBuffer) {
    511         native_handle_delete(nh);
    512         return false;
    513     }
    514 
    515     size_t const baseNumFds = getFenceFdCount(t);
    516     std::unique_ptr<int[]> baseFds(
    517             new (std::nothrow) int[baseNumFds]);
    518     if (!baseFds) {
    519         native_handle_delete(nh);
    520         return false;
    521     }
    522 
    523     void* buffer = static_cast<void*>(baseBuffer.get());
    524     size_t size = baseSize;
    525     int* fds = static_cast<int*>(baseFds.get());
    526     size_t numFds = baseNumFds;
    527     if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
    528         native_handle_delete(nh);
    529         return false;
    530     }
    531     native_handle_delete(nh);
    532 
    533     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
    534     size = baseSize;
    535     int const* constFds = static_cast<int const*>(baseFds.get());
    536     numFds = baseNumFds;
    537     if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
    538         return false;
    539     }
    540 
    541     return true;
    542 }
    543 
    544 // Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
    545 
    546 /**
    547  * \brief Return the size of the non-fd buffer required to flatten
    548  * `FenceTimeSnapshot`.
    549  *
    550  * \param[in] t The input `FenceTimeSnapshot`.
    551  * \return The required size of the flat buffer.
    552  */
    553 size_t getFlattenedSize(
    554         HGraphicBufferProducer::FenceTimeSnapshot const& t) {
    555     constexpr size_t min = sizeof(t.state);
    556     switch (t.state) {
    557         case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
    558             return min;
    559         case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
    560             return min + getFenceFlattenedSize(t.fence);
    561         case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
    562             return min + sizeof(
    563                     ::android::FenceTime::Snapshot::signalTime);
    564     }
    565     return 0;
    566 }
    567 
    568 /**
    569  * \brief Return the number of file descriptors contained in
    570  * `FenceTimeSnapshot`.
    571  *
    572  * \param[in] t The input `FenceTimeSnapshot`.
    573  * \return The number of file descriptors contained in \p snapshot.
    574  */
    575 size_t getFdCount(
    576         HGraphicBufferProducer::FenceTimeSnapshot const& t) {
    577     return t.state ==
    578             HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE ?
    579             getFenceFdCount(t.fence) : 0;
    580 }
    581 
    582 /**
    583  * \brief Flatten `FenceTimeSnapshot`.
    584  *
    585  * \param[in] t The source `FenceTimeSnapshot`.
    586  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    587  * \param[in,out] size The size of the flat non-fd buffer.
    588  * \param[in,out] fds The pointer to the flat fd buffer.
    589  * \param[in,out] numFds The size of the flat fd buffer.
    590  * \return `NO_ERROR` on success; other value on failure.
    591  *
    592  * This function will duplicate the file descriptor in `t.fence` if `t.state ==
    593  * FENCE`.
    594  */
    595 status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
    596         void*& buffer, size_t& size, int*& fds, size_t& numFds) {
    597     if (size < getFlattenedSize(t)) {
    598         return NO_MEMORY;
    599     }
    600 
    601     switch (t.state) {
    602         case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
    603             FlattenableUtils::write(buffer, size,
    604                     ::android::FenceTime::Snapshot::State::EMPTY);
    605             return NO_ERROR;
    606         case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
    607             FlattenableUtils::write(buffer, size,
    608                     ::android::FenceTime::Snapshot::State::FENCE);
    609             return flattenFence(t.fence, buffer, size, fds, numFds);
    610         case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
    611             FlattenableUtils::write(buffer, size,
    612                     ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
    613             FlattenableUtils::write(buffer, size, t.signalTimeNs);
    614             return NO_ERROR;
    615     }
    616     return NO_ERROR;
    617 }
    618 
    619 /**
    620  * \brief Unflatten `FenceTimeSnapshot`.
    621  *
    622  * \param[out] t The destination `FenceTimeSnapshot`.
    623  * \param[out] nh The underlying native handle.
    624  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    625  * \param[in,out] size The size of the flat non-fd buffer.
    626  * \param[in,out] fds The pointer to the flat fd buffer.
    627  * \param[in,out] numFds The size of the flat fd buffer.
    628  * \return `NO_ERROR` on success; other value on failure.
    629  *
    630  * If the return value is `NO_ERROR` and the constructed snapshot contains a
    631  * file descriptor, \p nh will be created to hold that file descriptor. In this
    632  * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
    633  */
    634 status_t unflatten(
    635         HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
    636         void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
    637     if (size < sizeof(t->state)) {
    638         return NO_MEMORY;
    639     }
    640 
    641     *nh = nullptr;
    642     ::android::FenceTime::Snapshot::State state;
    643     FlattenableUtils::read(buffer, size, state);
    644     switch (state) {
    645         case ::android::FenceTime::Snapshot::State::EMPTY:
    646             t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY;
    647             return NO_ERROR;
    648         case ::android::FenceTime::Snapshot::State::FENCE:
    649             t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE;
    650             return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
    651         case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
    652             t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
    653             if (size < sizeof(t->signalTimeNs)) {
    654                 return NO_MEMORY;
    655             }
    656             FlattenableUtils::read(buffer, size, t->signalTimeNs);
    657             return NO_ERROR;
    658     }
    659     return NO_ERROR;
    660 }
    661 
    662 // Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
    663 
    664 /**
    665  * \brief Return a lower bound on the size of the non-fd buffer required to
    666  * flatten `FrameEventsDelta`.
    667  *
    668  * \param[in] t The input `FrameEventsDelta`.
    669  * \return A lower bound on the size of the flat buffer.
    670  */
    671 constexpr size_t minFlattenedSize(
    672         HGraphicBufferProducer::FrameEventsDelta const& /* t */) {
    673     return sizeof(uint64_t) + // mFrameNumber
    674             sizeof(uint8_t) + // mIndex
    675             sizeof(uint8_t) + // mAddPostCompositeCalled
    676             sizeof(uint8_t) + // mAddRetireCalled
    677             sizeof(uint8_t) + // mAddReleaseCalled
    678             sizeof(nsecs_t) + // mPostedTime
    679             sizeof(nsecs_t) + // mRequestedPresentTime
    680             sizeof(nsecs_t) + // mLatchTime
    681             sizeof(nsecs_t) + // mFirstRefreshStartTime
    682             sizeof(nsecs_t); // mLastRefreshStartTime
    683 }
    684 
    685 /**
    686  * \brief Return the size of the non-fd buffer required to flatten
    687  * `FrameEventsDelta`.
    688  *
    689  * \param[in] t The input `FrameEventsDelta`.
    690  * \return The required size of the flat buffer.
    691  */
    692 size_t getFlattenedSize(
    693         HGraphicBufferProducer::FrameEventsDelta const& t) {
    694     return minFlattenedSize(t) +
    695             getFlattenedSize(t.gpuCompositionDoneFence) +
    696             getFlattenedSize(t.displayPresentFence) +
    697             getFlattenedSize(t.displayRetireFence) +
    698             getFlattenedSize(t.releaseFence);
    699 };
    700 
    701 /**
    702  * \brief Return the number of file descriptors contained in
    703  * `FrameEventsDelta`.
    704  *
    705  * \param[in] t The input `FrameEventsDelta`.
    706  * \return The number of file descriptors contained in \p t.
    707  */
    708 size_t getFdCount(
    709         HGraphicBufferProducer::FrameEventsDelta const& t) {
    710     return getFdCount(t.gpuCompositionDoneFence) +
    711             getFdCount(t.displayPresentFence) +
    712             getFdCount(t.displayRetireFence) +
    713             getFdCount(t.releaseFence);
    714 };
    715 
    716 /**
    717  * \brief Unflatten `FrameEventsDelta`.
    718  *
    719  * \param[out] t The destination `FrameEventsDelta`.
    720  * \param[out] nh The underlying array of native handles.
    721  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    722  * \param[in,out] size The size of the flat non-fd buffer.
    723  * \param[in,out] fds The pointer to the flat fd buffer.
    724  * \param[in,out] numFds The size of the flat fd buffer.
    725  * \return `NO_ERROR` on success; other value on failure.
    726  *
    727  * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
    728  * populated with `nullptr` or newly created handles. Each non-null slot in \p
    729  * nh will need to be deleted manually with `native_handle_delete()`.
    730  */
    731 status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
    732         std::vector<native_handle_t*>* nh,
    733         void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
    734     if (size < minFlattenedSize(*t)) {
    735         return NO_MEMORY;
    736     }
    737     FlattenableUtils::read(buffer, size, t->frameNumber);
    738 
    739     // These were written as uint8_t for alignment.
    740     uint8_t temp = 0;
    741     FlattenableUtils::read(buffer, size, temp);
    742     size_t index = static_cast<size_t>(temp);
    743     if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
    744         return BAD_VALUE;
    745     }
    746     t->index = static_cast<uint32_t>(index);
    747 
    748     FlattenableUtils::read(buffer, size, temp);
    749     t->addPostCompositeCalled = static_cast<bool>(temp);
    750     FlattenableUtils::read(buffer, size, temp);
    751     t->addRetireCalled = static_cast<bool>(temp);
    752     FlattenableUtils::read(buffer, size, temp);
    753     t->addReleaseCalled = static_cast<bool>(temp);
    754 
    755     FlattenableUtils::read(buffer, size, t->postedTimeNs);
    756     FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
    757     FlattenableUtils::read(buffer, size, t->latchTimeNs);
    758     FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
    759     FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
    760     FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
    761 
    762     // Fences
    763     HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
    764     tSnapshot[0] = &t->gpuCompositionDoneFence;
    765     tSnapshot[1] = &t->displayPresentFence;
    766     tSnapshot[2] = &t->displayRetireFence;
    767     tSnapshot[3] = &t->releaseFence;
    768     nh->resize(4);
    769     for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
    770         status_t status = unflatten(
    771                 tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
    772                 buffer, size, fds, numFds);
    773         if (status != NO_ERROR) {
    774             while (snapshotIndex > 0) {
    775                 --snapshotIndex;
    776                 if ((*nh)[snapshotIndex] != nullptr) {
    777                     native_handle_delete((*nh)[snapshotIndex]);
    778                 }
    779             }
    780             return status;
    781         }
    782     }
    783     return NO_ERROR;
    784 }
    785 
    786 /**
    787  * \brief Flatten `FrameEventsDelta`.
    788  *
    789  * \param[in] t The source `FrameEventsDelta`.
    790  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    791  * \param[in,out] size The size of the flat non-fd buffer.
    792  * \param[in,out] fds The pointer to the flat fd buffer.
    793  * \param[in,out] numFds The size of the flat fd buffer.
    794  * \return `NO_ERROR` on success; other value on failure.
    795  *
    796  * This function will duplicate file descriptors contained in \p t.
    797  */
    798 // Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
    799 //      FrameEventsDelta::flatten
    800 status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
    801         void*& buffer, size_t& size, int*& fds, size_t numFds) {
    802     // Check that t.index is within a valid range.
    803     if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
    804             || t.index > std::numeric_limits<uint8_t>::max()) {
    805         return BAD_VALUE;
    806     }
    807 
    808     FlattenableUtils::write(buffer, size, t.frameNumber);
    809 
    810     // These are static_cast to uint8_t for alignment.
    811     FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
    812     FlattenableUtils::write(
    813             buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
    814     FlattenableUtils::write(
    815             buffer, size, static_cast<uint8_t>(t.addRetireCalled));
    816     FlattenableUtils::write(
    817             buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
    818 
    819     FlattenableUtils::write(buffer, size, t.postedTimeNs);
    820     FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
    821     FlattenableUtils::write(buffer, size, t.latchTimeNs);
    822     FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
    823     FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
    824     FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
    825 
    826     // Fences
    827     HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
    828     tSnapshot[0] = &t.gpuCompositionDoneFence;
    829     tSnapshot[1] = &t.displayPresentFence;
    830     tSnapshot[2] = &t.displayRetireFence;
    831     tSnapshot[3] = &t.releaseFence;
    832     for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
    833         status_t status = flatten(
    834                 *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
    835         if (status != NO_ERROR) {
    836             return status;
    837         }
    838     }
    839     return NO_ERROR;
    840 }
    841 
    842 // Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
    843 
    844 /**
    845  * \brief Return the size of the non-fd buffer required to flatten
    846  * `HGraphicBufferProducer::FrameEventHistoryDelta`.
    847  *
    848  * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
    849  * \return The required size of the flat buffer.
    850  */
    851 size_t getFlattenedSize(
    852         HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
    853     size_t size = 4 + // mDeltas.size()
    854             sizeof(t.compositorTiming);
    855     for (size_t i = 0; i < t.deltas.size(); ++i) {
    856         size += getFlattenedSize(t.deltas[i]);
    857     }
    858     return size;
    859 }
    860 
    861 /**
    862  * \brief Return the number of file descriptors contained in
    863  * `HGraphicBufferProducer::FrameEventHistoryDelta`.
    864  *
    865  * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
    866  * \return The number of file descriptors contained in \p t.
    867  */
    868 size_t getFdCount(
    869         HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
    870     size_t numFds = 0;
    871     for (size_t i = 0; i < t.deltas.size(); ++i) {
    872         numFds += getFdCount(t.deltas[i]);
    873     }
    874     return numFds;
    875 }
    876 
    877 /**
    878  * \brief Unflatten `FrameEventHistoryDelta`.
    879  *
    880  * \param[out] t The destination `FrameEventHistoryDelta`.
    881  * \param[out] nh The underlying array of arrays of native handles.
    882  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    883  * \param[in,out] size The size of the flat non-fd buffer.
    884  * \param[in,out] fds The pointer to the flat fd buffer.
    885  * \param[in,out] numFds The size of the flat fd buffer.
    886  * \return `NO_ERROR` on success; other value on failure.
    887  *
    888  * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
    889  * newly created handles. The second dimension of \p nh will be 4. Each non-null
    890  * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
    891  */
    892 status_t unflatten(
    893         HGraphicBufferProducer::FrameEventHistoryDelta* t,
    894         std::vector<std::vector<native_handle_t*> >* nh,
    895         void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
    896     if (size < 4) {
    897         return NO_MEMORY;
    898     }
    899 
    900     FlattenableUtils::read(buffer, size, t->compositorTiming);
    901 
    902     uint32_t deltaCount = 0;
    903     FlattenableUtils::read(buffer, size, deltaCount);
    904     if (static_cast<size_t>(deltaCount) >
    905             ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
    906         return BAD_VALUE;
    907     }
    908     t->deltas.resize(deltaCount);
    909     nh->resize(deltaCount);
    910     for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
    911         status_t status = unflatten(
    912                 &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
    913                 buffer, size, fds, numFds);
    914         if (status != NO_ERROR) {
    915             return status;
    916         }
    917     }
    918     return NO_ERROR;
    919 }
    920 
    921 /**
    922  * \brief Flatten `FrameEventHistoryDelta`.
    923  *
    924  * \param[in] t The source `FrameEventHistoryDelta`.
    925  * \param[in,out] buffer The pointer to the flat non-fd buffer.
    926  * \param[in,out] size The size of the flat non-fd buffer.
    927  * \param[in,out] fds The pointer to the flat fd buffer.
    928  * \param[in,out] numFds The size of the flat fd buffer.
    929  * \return `NO_ERROR` on success; other value on failure.
    930  *
    931  * This function will duplicate file descriptors contained in \p t.
    932  */
    933 status_t flatten(
    934         HGraphicBufferProducer::FrameEventHistoryDelta const& t,
    935         void*& buffer, size_t& size, int*& fds, size_t& numFds) {
    936     if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
    937         return BAD_VALUE;
    938     }
    939     if (size < getFlattenedSize(t)) {
    940         return NO_MEMORY;
    941     }
    942 
    943     FlattenableUtils::write(buffer, size, t.compositorTiming);
    944 
    945     FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
    946     for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
    947         status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
    948         if (status != NO_ERROR) {
    949             return status;
    950         }
    951     }
    952     return NO_ERROR;
    953 }
    954 
    955 /**
    956  * \brief Wrap `::android::FrameEventHistoryData` in
    957  * `HGraphicBufferProducer::FrameEventHistoryDelta`.
    958  *
    959  * \param[out] t The wrapper of type
    960  * `HGraphicBufferProducer::FrameEventHistoryDelta`.
    961  * \param[out] nh The array of array of native handles that are referred to by
    962  * members of \p t.
    963  * \param[in] l The source `::android::FrameEventHistoryDelta`.
    964  *
    965  * On success, each member of \p nh will be either `nullptr` or a newly created
    966  * native handle. All the non-`nullptr` elements must be deleted individually
    967  * with `native_handle_delete()`.
    968  */
    969 bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
    970         std::vector<std::vector<native_handle_t*> >* nh,
    971         ::android::FrameEventHistoryDelta const& l) {
    972 
    973     size_t const baseSize = l.getFlattenedSize();
    974     std::unique_ptr<uint8_t[]> baseBuffer(
    975             new (std::nothrow) uint8_t[baseSize]);
    976     if (!baseBuffer) {
    977         return false;
    978     }
    979 
    980     size_t const baseNumFds = l.getFdCount();
    981     std::unique_ptr<int[]> baseFds(
    982             new (std::nothrow) int[baseNumFds]);
    983     if (!baseFds) {
    984         return false;
    985     }
    986 
    987     void* buffer = static_cast<void*>(baseBuffer.get());
    988     size_t size = baseSize;
    989     int* fds = baseFds.get();
    990     size_t numFds = baseNumFds;
    991     if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
    992         return false;
    993     }
    994 
    995     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
    996     size = baseSize;
    997     int const* constFds = static_cast<int const*>(baseFds.get());
    998     numFds = baseNumFds;
    999     if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
   1000         return false;
   1001     }
   1002 
   1003     return true;
   1004 }
   1005 
   1006 /**
   1007  * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
   1008  * `::android::FrameEventHistoryDelta`.
   1009  *
   1010  * \param[out] l The destination `::android::FrameEventHistoryDelta`.
   1011  * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
   1012  *
   1013  * This function will duplicate all file descriptors contained in \p t.
   1014  */
   1015 bool convertTo(
   1016         ::android::FrameEventHistoryDelta* l,
   1017         HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
   1018 
   1019     size_t const baseSize = getFlattenedSize(t);
   1020     std::unique_ptr<uint8_t[]> baseBuffer(
   1021             new (std::nothrow) uint8_t[baseSize]);
   1022     if (!baseBuffer) {
   1023         return false;
   1024     }
   1025 
   1026     size_t const baseNumFds = getFdCount(t);
   1027     std::unique_ptr<int[]> baseFds(
   1028             new (std::nothrow) int[baseNumFds]);
   1029     if (!baseFds) {
   1030         return false;
   1031     }
   1032 
   1033     void* buffer = static_cast<void*>(baseBuffer.get());
   1034     size_t size = baseSize;
   1035     int* fds = static_cast<int*>(baseFds.get());
   1036     size_t numFds = baseNumFds;
   1037     if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
   1038         return false;
   1039     }
   1040 
   1041     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
   1042     size = baseSize;
   1043     int const* constFds = static_cast<int const*>(baseFds.get());
   1044     numFds = baseNumFds;
   1045     if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
   1046         return false;
   1047     }
   1048 
   1049     return true;
   1050 }
   1051 
   1052 // Ref: frameworks/native/libs/ui/Region.cpp
   1053 
   1054 /**
   1055  * \brief Return the size of the buffer required to flatten `Region`.
   1056  *
   1057  * \param[in] t The input `Region`.
   1058  * \return The required size of the flat buffer.
   1059  */
   1060 size_t getFlattenedSize(Region const& t) {
   1061     return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
   1062 }
   1063 
   1064 /**
   1065  * \brief Unflatten `Region`.
   1066  *
   1067  * \param[out] t The destination `Region`.
   1068  * \param[in,out] buffer The pointer to the flat buffer.
   1069  * \param[in,out] size The size of the flat buffer.
   1070  * \return `NO_ERROR` on success; other value on failure.
   1071  */
   1072 status_t unflatten(Region* t, void const*& buffer, size_t& size) {
   1073     if (size < sizeof(uint32_t)) {
   1074         return NO_MEMORY;
   1075     }
   1076 
   1077     uint32_t numRects = 0;
   1078     FlattenableUtils::read(buffer, size, numRects);
   1079     if (size < numRects * sizeof(Rect)) {
   1080         return NO_MEMORY;
   1081     }
   1082     if (numRects > (UINT32_MAX / sizeof(Rect))) {
   1083         return NO_MEMORY;
   1084     }
   1085 
   1086     t->resize(numRects);
   1087     for (size_t r = 0; r < numRects; ++r) {
   1088         ::android::Rect rect(::android::Rect::EMPTY_RECT);
   1089         status_t status = rect.unflatten(buffer, size);
   1090         if (status != NO_ERROR) {
   1091             return status;
   1092         }
   1093         FlattenableUtils::advance(buffer, size, sizeof(rect));
   1094         (*t)[r] = Rect{
   1095                 static_cast<int32_t>(rect.left),
   1096                 static_cast<int32_t>(rect.top),
   1097                 static_cast<int32_t>(rect.right),
   1098                 static_cast<int32_t>(rect.bottom)};
   1099     }
   1100     return NO_ERROR;
   1101 }
   1102 
   1103 /**
   1104  * \brief Flatten `Region`.
   1105  *
   1106  * \param[in] t The source `Region`.
   1107  * \param[in,out] buffer The pointer to the flat buffer.
   1108  * \param[in,out] size The size of the flat buffer.
   1109  * \return `NO_ERROR` on success; other value on failure.
   1110  */
   1111 status_t flatten(Region const& t, void*& buffer, size_t& size) {
   1112     if (size < getFlattenedSize(t)) {
   1113         return NO_MEMORY;
   1114     }
   1115 
   1116     FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
   1117     for (size_t r = 0; r < t.size(); ++r) {
   1118         ::android::Rect rect(
   1119                 static_cast<int32_t>(t[r].left),
   1120                 static_cast<int32_t>(t[r].top),
   1121                 static_cast<int32_t>(t[r].right),
   1122                 static_cast<int32_t>(t[r].bottom));
   1123         status_t status = rect.flatten(buffer, size);
   1124         if (status != NO_ERROR) {
   1125             return status;
   1126         }
   1127         FlattenableUtils::advance(buffer, size, sizeof(rect));
   1128     }
   1129     return NO_ERROR;
   1130 }
   1131 
   1132 /**
   1133  * \brief Convert `::android::Region` to `Region`.
   1134  *
   1135  * \param[out] t The destination `Region`.
   1136  * \param[in] l The source `::android::Region`.
   1137  */
   1138 // convert: ::android::Region -> Region
   1139 bool convertTo(Region* t, ::android::Region const& l) {
   1140     size_t const baseSize = l.getFlattenedSize();
   1141     std::unique_ptr<uint8_t[]> baseBuffer(
   1142             new (std::nothrow) uint8_t[baseSize]);
   1143     if (!baseBuffer) {
   1144         return false;
   1145     }
   1146 
   1147     void* buffer = static_cast<void*>(baseBuffer.get());
   1148     size_t size = baseSize;
   1149     if (l.flatten(buffer, size) != NO_ERROR) {
   1150         return false;
   1151     }
   1152 
   1153     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
   1154     size = baseSize;
   1155     if (unflatten(t, constBuffer, size) != NO_ERROR) {
   1156         return false;
   1157     }
   1158 
   1159     return true;
   1160 }
   1161 
   1162 /**
   1163  * \brief Convert `Region` to `::android::Region`.
   1164  *
   1165  * \param[out] l The destination `::android::Region`.
   1166  * \param[in] t The source `Region`.
   1167  */
   1168 // convert: Region -> ::android::Region
   1169 bool convertTo(::android::Region* l, Region const& t) {
   1170     size_t const baseSize = getFlattenedSize(t);
   1171     std::unique_ptr<uint8_t[]> baseBuffer(
   1172             new (std::nothrow) uint8_t[baseSize]);
   1173     if (!baseBuffer) {
   1174         return false;
   1175     }
   1176 
   1177     void* buffer = static_cast<void*>(baseBuffer.get());
   1178     size_t size = baseSize;
   1179     if (flatten(t, buffer, size) != NO_ERROR) {
   1180         return false;
   1181     }
   1182 
   1183     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
   1184     size = baseSize;
   1185     if (l->unflatten(constBuffer, size) != NO_ERROR) {
   1186         return false;
   1187     }
   1188 
   1189     return true;
   1190 }
   1191 
   1192 // Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
   1193 //      BGraphicBufferProducer::QueueBufferInput
   1194 
   1195 /**
   1196  * \brief Return a lower bound on the size of the buffer required to flatten
   1197  * `HGraphicBufferProducer::QueueBufferInput`.
   1198  *
   1199  * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
   1200  * \return A lower bound on the size of the flat buffer.
   1201  */
   1202 constexpr size_t minFlattenedSize(
   1203         HGraphicBufferProducer::QueueBufferInput const& /* t */) {
   1204     return sizeof(int64_t) + // timestamp
   1205             sizeof(int) + // isAutoTimestamp
   1206             sizeof(android_dataspace) + // dataSpace
   1207             sizeof(::android::Rect) + // crop
   1208             sizeof(int) + // scalingMode
   1209             sizeof(uint32_t) + // transform
   1210             sizeof(uint32_t) + // stickyTransform
   1211             sizeof(bool); // getFrameTimestamps
   1212 }
   1213 
   1214 /**
   1215  * \brief Return the size of the buffer required to flatten
   1216  * `HGraphicBufferProducer::QueueBufferInput`.
   1217  *
   1218  * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
   1219  * \return The required size of the flat buffer.
   1220  */
   1221 size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
   1222     return minFlattenedSize(t) +
   1223             getFenceFlattenedSize(t.fence) +
   1224             getFlattenedSize(t.surfaceDamage) +
   1225             sizeof(HdrMetadata::validTypes);
   1226 }
   1227 
   1228 /**
   1229  * \brief Return the number of file descriptors contained in
   1230  * `HGraphicBufferProducer::QueueBufferInput`.
   1231  *
   1232  * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
   1233  * \return The number of file descriptors contained in \p t.
   1234  */
   1235 size_t getFdCount(
   1236         HGraphicBufferProducer::QueueBufferInput const& t) {
   1237     return getFenceFdCount(t.fence);
   1238 }
   1239 
   1240 /**
   1241  * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
   1242  *
   1243  * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
   1244  * \param[out] nh The native handle cloned from `t.fence`.
   1245  * \param[in,out] buffer The pointer to the flat non-fd buffer.
   1246  * \param[in,out] size The size of the flat non-fd buffer.
   1247  * \param[in,out] fds The pointer to the flat fd buffer.
   1248  * \param[in,out] numFds The size of the flat fd buffer.
   1249  * \return `NO_ERROR` on success; other value on failure.
   1250  *
   1251  * This function will duplicate the file descriptor in `t.fence`. */
   1252 status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
   1253         native_handle_t** nh,
   1254         void*& buffer, size_t& size, int*& fds, size_t& numFds) {
   1255     if (size < getFlattenedSize(t)) {
   1256         return NO_MEMORY;
   1257     }
   1258 
   1259     FlattenableUtils::write(buffer, size, t.timestamp);
   1260     FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
   1261     FlattenableUtils::write(buffer, size,
   1262             static_cast<android_dataspace_t>(t.dataSpace));
   1263     FlattenableUtils::write(buffer, size, ::android::Rect(
   1264             static_cast<int32_t>(t.crop.left),
   1265             static_cast<int32_t>(t.crop.top),
   1266             static_cast<int32_t>(t.crop.right),
   1267             static_cast<int32_t>(t.crop.bottom)));
   1268     FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
   1269     FlattenableUtils::write(buffer, size, t.transform);
   1270     FlattenableUtils::write(buffer, size, t.stickyTransform);
   1271     FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
   1272 
   1273     *nh = t.fence.getNativeHandle() == nullptr ?
   1274             nullptr : native_handle_clone(t.fence);
   1275     status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
   1276     if (status != NO_ERROR) {
   1277         return status;
   1278     }
   1279     status = flatten(t.surfaceDamage, buffer, size);
   1280     if (status != NO_ERROR) {
   1281         return status;
   1282     }
   1283     FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
   1284     return NO_ERROR;
   1285 }
   1286 
   1287 /**
   1288  * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
   1289  *
   1290  * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
   1291  * \param[out] nh The underlying native handle for `t->fence`.
   1292  * \param[in,out] buffer The pointer to the flat non-fd buffer.
   1293  * \param[in,out] size The size of the flat non-fd buffer.
   1294  * \param[in,out] fds The pointer to the flat fd buffer.
   1295  * \param[in,out] numFds The size of the flat fd buffer.
   1296  * \return `NO_ERROR` on success; other value on failure.
   1297  *
   1298  * If the return value is `NO_ERROR` and `t->fence` contains a valid file
   1299  * descriptor, \p nh will be a newly created native handle holding that file
   1300  * descriptor. \p nh needs to be deleted with `native_handle_delete()`
   1301  * afterwards.
   1302  */
   1303 status_t unflatten(
   1304         HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
   1305         void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
   1306     if (size < minFlattenedSize(*t)) {
   1307         return NO_MEMORY;
   1308     }
   1309 
   1310     FlattenableUtils::read(buffer, size, t->timestamp);
   1311     int lIsAutoTimestamp;
   1312     FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
   1313     t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
   1314     android_dataspace_t lDataSpace;
   1315     FlattenableUtils::read(buffer, size, lDataSpace);
   1316     t->dataSpace = static_cast<Dataspace>(lDataSpace);
   1317     Rect lCrop;
   1318     FlattenableUtils::read(buffer, size, lCrop);
   1319     t->crop = Rect{
   1320             static_cast<int32_t>(lCrop.left),
   1321             static_cast<int32_t>(lCrop.top),
   1322             static_cast<int32_t>(lCrop.right),
   1323             static_cast<int32_t>(lCrop.bottom)};
   1324     int lScalingMode;
   1325     FlattenableUtils::read(buffer, size, lScalingMode);
   1326     t->scalingMode = static_cast<int32_t>(lScalingMode);
   1327     FlattenableUtils::read(buffer, size, t->transform);
   1328     FlattenableUtils::read(buffer, size, t->stickyTransform);
   1329     FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
   1330 
   1331     status_t status = unflattenFence(&(t->fence), nh,
   1332             buffer, size, fds, numFds);
   1333     if (status != NO_ERROR) {
   1334         return status;
   1335     }
   1336     // HdrMetadata ignored
   1337     return unflatten(&(t->surfaceDamage), buffer, size);
   1338 }
   1339 
   1340 /**
   1341  * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
   1342  * `HGraphicBufferProducer::QueueBufferInput`.
   1343  *
   1344  * \param[out] t The wrapper of type
   1345  * `HGraphicBufferProducer::QueueBufferInput`.
   1346  * \param[out] nh The underlying native handle for `t->fence`.
   1347  * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
   1348  *
   1349  * If the return value is `true` and `t->fence` contains a valid file
   1350  * descriptor, \p nh will be a newly created native handle holding that file
   1351  * descriptor. \p nh needs to be deleted with `native_handle_delete()`
   1352  * afterwards.
   1353  */
   1354 bool wrapAs(
   1355         HGraphicBufferProducer::QueueBufferInput* t,
   1356         native_handle_t** nh,
   1357         BGraphicBufferProducer::QueueBufferInput const& l) {
   1358 
   1359     size_t const baseSize = l.getFlattenedSize();
   1360     std::unique_ptr<uint8_t[]> baseBuffer(
   1361             new (std::nothrow) uint8_t[baseSize]);
   1362     if (!baseBuffer) {
   1363         return false;
   1364     }
   1365 
   1366     size_t const baseNumFds = l.getFdCount();
   1367     std::unique_ptr<int[]> baseFds(
   1368             new (std::nothrow) int[baseNumFds]);
   1369     if (!baseFds) {
   1370         return false;
   1371     }
   1372 
   1373     void* buffer = static_cast<void*>(baseBuffer.get());
   1374     size_t size = baseSize;
   1375     int* fds = baseFds.get();
   1376     size_t numFds = baseNumFds;
   1377     if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
   1378         return false;
   1379     }
   1380 
   1381     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
   1382     size = baseSize;
   1383     int const* constFds = static_cast<int const*>(baseFds.get());
   1384     numFds = baseNumFds;
   1385     if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
   1386         return false;
   1387     }
   1388 
   1389     return true;
   1390 }
   1391 
   1392 /**
   1393  * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
   1394  * `BGraphicBufferProducer::QueueBufferInput`.
   1395  *
   1396  * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
   1397  * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
   1398  *
   1399  * If `t.fence` has a valid file descriptor, it will be duplicated.
   1400  */
   1401 bool convertTo(
   1402         BGraphicBufferProducer::QueueBufferInput* l,
   1403         HGraphicBufferProducer::QueueBufferInput const& t) {
   1404 
   1405     size_t const baseSize = getFlattenedSize(t);
   1406     std::unique_ptr<uint8_t[]> baseBuffer(
   1407             new (std::nothrow) uint8_t[baseSize]);
   1408     if (!baseBuffer) {
   1409         return false;
   1410     }
   1411 
   1412     size_t const baseNumFds = getFdCount(t);
   1413     std::unique_ptr<int[]> baseFds(
   1414             new (std::nothrow) int[baseNumFds]);
   1415     if (!baseFds) {
   1416         return false;
   1417     }
   1418 
   1419     void* buffer = static_cast<void*>(baseBuffer.get());
   1420     size_t size = baseSize;
   1421     int* fds = baseFds.get();
   1422     size_t numFds = baseNumFds;
   1423     native_handle_t* nh;
   1424     if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
   1425         return false;
   1426     }
   1427 
   1428     void const* constBuffer = static_cast<void const*>(baseBuffer.get());
   1429     size = baseSize;
   1430     int const* constFds = static_cast<int const*>(baseFds.get());
   1431     numFds = baseNumFds;
   1432     if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
   1433         if (nh != nullptr) {
   1434             native_handle_close(nh);
   1435             native_handle_delete(nh);
   1436         }
   1437         return false;
   1438     }
   1439 
   1440     native_handle_delete(nh);
   1441     return true;
   1442 }
   1443 
   1444 // Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
   1445 //      BGraphicBufferProducer::QueueBufferOutput
   1446 
   1447 /**
   1448  * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
   1449  * `HGraphicBufferProducer::QueueBufferOutput`.
   1450  *
   1451  * \param[out] t The wrapper of type
   1452  * `HGraphicBufferProducer::QueueBufferOutput`.
   1453  * \param[out] nh The array of array of native handles that are referred to by
   1454  * members of \p t.
   1455  * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
   1456  *
   1457  * On success, each member of \p nh will be either `nullptr` or a newly created
   1458  * native handle. All the non-`nullptr` elements must be deleted individually
   1459  * with `native_handle_delete()`.
   1460  */
   1461 // wrap: BGraphicBufferProducer::QueueBufferOutput ->
   1462 // HGraphicBufferProducer::QueueBufferOutput
   1463 bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
   1464         std::vector<std::vector<native_handle_t*> >* nh,
   1465         BGraphicBufferProducer::QueueBufferOutput const& l) {
   1466     if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
   1467         return false;
   1468     }
   1469     t->width = l.width;
   1470     t->height = l.height;
   1471     t->transformHint = l.transformHint;
   1472     t->numPendingBuffers = l.numPendingBuffers;
   1473     t->nextFrameNumber = l.nextFrameNumber;
   1474     t->bufferReplaced = l.bufferReplaced;
   1475     return true;
   1476 }
   1477 
   1478 /**
   1479  * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
   1480  * `BGraphicBufferProducer::QueueBufferOutput`.
   1481  *
   1482  * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
   1483  * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
   1484  *
   1485  * This function will duplicate all file descriptors contained in \p t.
   1486  */
   1487 // convert: HGraphicBufferProducer::QueueBufferOutput ->
   1488 // BGraphicBufferProducer::QueueBufferOutput
   1489 bool convertTo(
   1490         BGraphicBufferProducer::QueueBufferOutput* l,
   1491         HGraphicBufferProducer::QueueBufferOutput const& t) {
   1492     if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
   1493         return false;
   1494     }
   1495     l->width = t.width;
   1496     l->height = t.height;
   1497     l->transformHint = t.transformHint;
   1498     l->numPendingBuffers = t.numPendingBuffers;
   1499     l->nextFrameNumber = t.nextFrameNumber;
   1500     l->bufferReplaced = t.bufferReplaced;
   1501     return true;
   1502 }
   1503 
   1504 /**
   1505  * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
   1506  * `HGraphicBufferProducer::DisconnectMode`.
   1507  *
   1508  * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
   1509  * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
   1510  */
   1511 HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
   1512         BGraphicBufferProducer::DisconnectMode l) {
   1513     switch (l) {
   1514         case BGraphicBufferProducer::DisconnectMode::Api:
   1515             return HGraphicBufferProducer::DisconnectMode::API;
   1516         case BGraphicBufferProducer::DisconnectMode::AllLocal:
   1517             return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
   1518     }
   1519     return HGraphicBufferProducer::DisconnectMode::API;
   1520 }
   1521 
   1522 /**
   1523  * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
   1524  * `BGraphicBufferProducer::DisconnectMode`.
   1525  *
   1526  * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
   1527  * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
   1528  */
   1529 BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
   1530         HGraphicBufferProducer::DisconnectMode t) {
   1531     switch (t) {
   1532         case HGraphicBufferProducer::DisconnectMode::API:
   1533             return BGraphicBufferProducer::DisconnectMode::Api;
   1534         case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
   1535             return BGraphicBufferProducer::DisconnectMode::AllLocal;
   1536     }
   1537     return BGraphicBufferProducer::DisconnectMode::Api;
   1538 }
   1539 
   1540 }  // namespace conversion
   1541 }  // namespace android
   1542 
   1543