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