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 Convert `Return<void>` to `binder::Status`.
113  *
114  * \param[in] t The source `Return<void>`.
115  * \return The corresponding `binder::Status`.
116  */
117 // convert: Return<void> -> ::android::binder::Status
toBinderStatus(Return<void> const & t)118 ::android::binder::Status toBinderStatus(
119         Return<void> const& t) {
120     return ::android::binder::Status::fromExceptionCode(
121             toStatusT(t),
122             t.description().c_str());
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
inHidlHandle(native_handle_t const * nh)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
toHardwareDataspace(int32_t l)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
toRawDataspace(Dataspace const & 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>
inHidlBytes(void const * l,size_t size)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>
toHidlBytes(void const * l,size_t size)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
wrapAs(AnwBuffer * t,GraphicBuffer const & l)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 = static_cast<uint32_t>(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
convertTo(GraphicBuffer * l,AnwBuffer const & t)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 + static_cast<size_t>(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  */
getFenceFlattenedSize(hidl_handle const &)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  */
getFenceFdCount(hidl_handle const & fence)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  */
unflattenFence(hidl_handle * fence,native_handle_t ** nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)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  */
flattenFence(hidl_handle const & fence,void * & buffer,size_t & size,int * & fds,size_t & numFds)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
wrapAs(hidl_handle * t,native_handle_t ** nh,Fence const & l)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
convertTo(Fence * l,hidl_handle const & t)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  */
getFlattenedSize(HGraphicBufferProducer::FenceTimeSnapshot const & t)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  */
getFdCount(HGraphicBufferProducer::FenceTimeSnapshot const & t)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  */
flatten(HGraphicBufferProducer::FenceTimeSnapshot const & t,void * & buffer,size_t & size,int * & fds,size_t & numFds)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  */
unflatten(HGraphicBufferProducer::FenceTimeSnapshot * t,native_handle_t ** nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)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  */
minFlattenedSize(HGraphicBufferProducer::FrameEventsDelta const &)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  */
getFlattenedSize(HGraphicBufferProducer::FrameEventsDelta const & t)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  */
getFdCount(HGraphicBufferProducer::FrameEventsDelta const & t)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  */
unflatten(HGraphicBufferProducer::FrameEventsDelta * t,std::vector<native_handle_t * > * nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)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
flatten(HGraphicBufferProducer::FrameEventsDelta const & t,void * & buffer,size_t & size,int * & fds,size_t numFds)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  */
getFlattenedSize(HGraphicBufferProducer::FrameEventHistoryDelta const & t)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  */
getFdCount(HGraphicBufferProducer::FrameEventHistoryDelta const & t)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  */
unflatten(HGraphicBufferProducer::FrameEventHistoryDelta * t,std::vector<std::vector<native_handle_t * >> * nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)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  */
flatten(HGraphicBufferProducer::FrameEventHistoryDelta const & t,void * & buffer,size_t & size,int * & fds,size_t & numFds)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  */
wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta * t,std::vector<std::vector<native_handle_t * >> * nh,::android::FrameEventHistoryDelta const & l)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  */
convertTo(::android::FrameEventHistoryDelta * l,HGraphicBufferProducer::FrameEventHistoryDelta const & t)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  */
getFlattenedSize(Region const & t)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  */
unflatten(Region * t,void const * & buffer,size_t & size)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  */
flatten(Region const & t,void * & buffer,size_t & size)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
convertTo(Region * t,::android::Region const & l)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
convertTo(::android::Region * l,Region const & t)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  */
minFlattenedSize(HGraphicBufferProducer::QueueBufferInput const &)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  */
getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const & t)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  */
getFdCount(HGraphicBufferProducer::QueueBufferInput const & t)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`. */
flatten(HGraphicBufferProducer::QueueBufferInput const & t,native_handle_t ** nh,void * & buffer,size_t & size,int * & fds,size_t & numFds)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  */
unflatten(HGraphicBufferProducer::QueueBufferInput * t,native_handle_t ** nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)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  */
wrapAs(HGraphicBufferProducer::QueueBufferInput * t,native_handle_t ** nh,BGraphicBufferProducer::QueueBufferInput const & l)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  */
convertTo(BGraphicBufferProducer::QueueBufferInput * l,HGraphicBufferProducer::QueueBufferInput const & t)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
wrapAs(HGraphicBufferProducer::QueueBufferOutput * t,std::vector<std::vector<native_handle_t * >> * nh,BGraphicBufferProducer::QueueBufferOutput const & l)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
convertTo(BGraphicBufferProducer::QueueBufferOutput * l,HGraphicBufferProducer::QueueBufferOutput const & t)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  */
toHidlDisconnectMode(BGraphicBufferProducer::DisconnectMode l)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  */
toGuiDisconnectMode(HGraphicBufferProducer::DisconnectMode t)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