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 t->index = static_cast<uint32_t>(temp);
729 FlattenableUtils::read(buffer, size, temp);
730 t->addPostCompositeCalled = static_cast<bool>(temp);
731 FlattenableUtils::read(buffer, size, temp);
732 t->addRetireCalled = static_cast<bool>(temp);
733 FlattenableUtils::read(buffer, size, temp);
734 t->addReleaseCalled = static_cast<bool>(temp);
735
736 FlattenableUtils::read(buffer, size, t->postedTimeNs);
737 FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
738 FlattenableUtils::read(buffer, size, t->latchTimeNs);
739 FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
740 FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
741 FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
742
743 // Fences
744 HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
745 tSnapshot[0] = &t->gpuCompositionDoneFence;
746 tSnapshot[1] = &t->displayPresentFence;
747 tSnapshot[2] = &t->displayRetireFence;
748 tSnapshot[3] = &t->releaseFence;
749 nh->resize(4);
750 for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
751 status_t status = unflatten(
752 tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
753 buffer, size, fds, numFds);
754 if (status != NO_ERROR) {
755 while (snapshotIndex > 0) {
756 --snapshotIndex;
757 if ((*nh)[snapshotIndex] != nullptr) {
758 native_handle_delete((*nh)[snapshotIndex]);
759 }
760 }
761 return status;
762 }
763 }
764 return NO_ERROR;
765 }
766
767 /**
768 * \brief Flatten `FrameEventsDelta`.
769 *
770 * \param[in] t The source `FrameEventsDelta`.
771 * \param[in,out] buffer The pointer to the flat non-fd buffer.
772 * \param[in,out] size The size of the flat non-fd buffer.
773 * \param[in,out] fds The pointer to the flat fd buffer.
774 * \param[in,out] numFds The size of the flat fd buffer.
775 * \return `NO_ERROR` on success; other value on failure.
776 *
777 * This function will duplicate file descriptors contained in \p t.
778 */
779 // Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
780 // FrameEventsDelta::flatten
flatten(HGraphicBufferProducer::FrameEventsDelta const & t,void * & buffer,size_t & size,int * & fds,size_t numFds)781 status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
782 void*& buffer, size_t& size, int*& fds, size_t numFds) {
783 // Check that t.index is within a valid range.
784 if (t.index > UINT8_MAX || t.index < 0) {
785 return BAD_VALUE;
786 }
787
788 FlattenableUtils::write(buffer, size, t.frameNumber);
789
790 // These are static_cast to uint8_t for alignment.
791 FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
792 FlattenableUtils::write(
793 buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
794 FlattenableUtils::write(
795 buffer, size, static_cast<uint8_t>(t.addRetireCalled));
796 FlattenableUtils::write(
797 buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
798
799 FlattenableUtils::write(buffer, size, t.postedTimeNs);
800 FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
801 FlattenableUtils::write(buffer, size, t.latchTimeNs);
802 FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
803 FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
804 FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
805
806 // Fences
807 HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
808 tSnapshot[0] = &t.gpuCompositionDoneFence;
809 tSnapshot[1] = &t.displayPresentFence;
810 tSnapshot[2] = &t.displayRetireFence;
811 tSnapshot[3] = &t.releaseFence;
812 for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
813 status_t status = flatten(
814 *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
815 if (status != NO_ERROR) {
816 return status;
817 }
818 }
819 return NO_ERROR;
820 }
821
822 // Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
823
824 /**
825 * \brief Return the size of the non-fd buffer required to flatten
826 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
827 *
828 * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
829 * \return The required size of the flat buffer.
830 */
getFlattenedSize(HGraphicBufferProducer::FrameEventHistoryDelta const & t)831 size_t getFlattenedSize(
832 HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
833 size_t size = 4 + // mDeltas.size()
834 sizeof(t.compositorTiming);
835 for (size_t i = 0; i < t.deltas.size(); ++i) {
836 size += getFlattenedSize(t.deltas[i]);
837 }
838 return size;
839 }
840
841 /**
842 * \brief Return the number of file descriptors contained in
843 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
844 *
845 * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
846 * \return The number of file descriptors contained in \p t.
847 */
getFdCount(HGraphicBufferProducer::FrameEventHistoryDelta const & t)848 size_t getFdCount(
849 HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
850 size_t numFds = 0;
851 for (size_t i = 0; i < t.deltas.size(); ++i) {
852 numFds += getFdCount(t.deltas[i]);
853 }
854 return numFds;
855 }
856
857 /**
858 * \brief Unflatten `FrameEventHistoryDelta`.
859 *
860 * \param[out] t The destination `FrameEventHistoryDelta`.
861 * \param[out] nh The underlying array of arrays of native handles.
862 * \param[in,out] buffer The pointer to the flat non-fd buffer.
863 * \param[in,out] size The size of the flat non-fd buffer.
864 * \param[in,out] fds The pointer to the flat fd buffer.
865 * \param[in,out] numFds The size of the flat fd buffer.
866 * \return `NO_ERROR` on success; other value on failure.
867 *
868 * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
869 * newly created handles. The second dimension of \p nh will be 4. Each non-null
870 * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
871 */
unflatten(HGraphicBufferProducer::FrameEventHistoryDelta * t,std::vector<std::vector<native_handle_t * >> * nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)872 status_t unflatten(
873 HGraphicBufferProducer::FrameEventHistoryDelta* t,
874 std::vector<std::vector<native_handle_t*> >* nh,
875 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
876 if (size < 4) {
877 return NO_MEMORY;
878 }
879
880 FlattenableUtils::read(buffer, size, t->compositorTiming);
881
882 uint32_t deltaCount = 0;
883 FlattenableUtils::read(buffer, size, deltaCount);
884 if (deltaCount > UINT8_MAX) {
885 return BAD_VALUE;
886 }
887 t->deltas.resize(deltaCount);
888 nh->resize(deltaCount);
889 for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
890 status_t status = unflatten(
891 &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
892 buffer, size, fds, numFds);
893 if (status != NO_ERROR) {
894 return status;
895 }
896 }
897 return NO_ERROR;
898 }
899
900 /**
901 * \brief Flatten `FrameEventHistoryDelta`.
902 *
903 * \param[in] t The source `FrameEventHistoryDelta`.
904 * \param[in,out] buffer The pointer to the flat non-fd buffer.
905 * \param[in,out] size The size of the flat non-fd buffer.
906 * \param[in,out] fds The pointer to the flat fd buffer.
907 * \param[in,out] numFds The size of the flat fd buffer.
908 * \return `NO_ERROR` on success; other value on failure.
909 *
910 * This function will duplicate file descriptors contained in \p t.
911 */
flatten(HGraphicBufferProducer::FrameEventHistoryDelta const & t,void * & buffer,size_t & size,int * & fds,size_t & numFds)912 status_t flatten(
913 HGraphicBufferProducer::FrameEventHistoryDelta const& t,
914 void*& buffer, size_t& size, int*& fds, size_t& numFds) {
915 if (t.deltas.size() > UINT8_MAX) {
916 return BAD_VALUE;
917 }
918 if (size < getFlattenedSize(t)) {
919 return NO_MEMORY;
920 }
921
922 FlattenableUtils::write(buffer, size, t.compositorTiming);
923
924 FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
925 for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
926 status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
927 if (status != NO_ERROR) {
928 return status;
929 }
930 }
931 return NO_ERROR;
932 }
933
934 /**
935 * \brief Wrap `::android::FrameEventHistoryData` in
936 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
937 *
938 * \param[out] t The wrapper of type
939 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
940 * \param[out] nh The array of array of native handles that are referred to by
941 * members of \p t.
942 * \param[in] l The source `::android::FrameEventHistoryDelta`.
943 *
944 * On success, each member of \p nh will be either `nullptr` or a newly created
945 * native handle. All the non-`nullptr` elements must be deleted individually
946 * with `native_handle_delete()`.
947 */
wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta * t,std::vector<std::vector<native_handle_t * >> * nh,::android::FrameEventHistoryDelta const & l)948 bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
949 std::vector<std::vector<native_handle_t*> >* nh,
950 ::android::FrameEventHistoryDelta const& l) {
951
952 size_t const baseSize = l.getFlattenedSize();
953 std::unique_ptr<uint8_t[]> baseBuffer(
954 new (std::nothrow) uint8_t[baseSize]);
955 if (!baseBuffer) {
956 return false;
957 }
958
959 size_t const baseNumFds = l.getFdCount();
960 std::unique_ptr<int[]> baseFds(
961 new (std::nothrow) int[baseNumFds]);
962 if (!baseFds) {
963 return false;
964 }
965
966 void* buffer = static_cast<void*>(baseBuffer.get());
967 size_t size = baseSize;
968 int* fds = baseFds.get();
969 size_t numFds = baseNumFds;
970 if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
971 return false;
972 }
973
974 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
975 size = baseSize;
976 int const* constFds = static_cast<int const*>(baseFds.get());
977 numFds = baseNumFds;
978 if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
979 return false;
980 }
981
982 return true;
983 }
984
985 /**
986 * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
987 * `::android::FrameEventHistoryDelta`.
988 *
989 * \param[out] l The destination `::android::FrameEventHistoryDelta`.
990 * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
991 *
992 * This function will duplicate all file descriptors contained in \p t.
993 */
convertTo(::android::FrameEventHistoryDelta * l,HGraphicBufferProducer::FrameEventHistoryDelta const & t)994 bool convertTo(
995 ::android::FrameEventHistoryDelta* l,
996 HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
997
998 size_t const baseSize = getFlattenedSize(t);
999 std::unique_ptr<uint8_t[]> baseBuffer(
1000 new (std::nothrow) uint8_t[baseSize]);
1001 if (!baseBuffer) {
1002 return false;
1003 }
1004
1005 size_t const baseNumFds = getFdCount(t);
1006 std::unique_ptr<int[]> baseFds(
1007 new (std::nothrow) int[baseNumFds]);
1008 if (!baseFds) {
1009 return false;
1010 }
1011
1012 void* buffer = static_cast<void*>(baseBuffer.get());
1013 size_t size = baseSize;
1014 int* fds = static_cast<int*>(baseFds.get());
1015 size_t numFds = baseNumFds;
1016 if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
1017 return false;
1018 }
1019
1020 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1021 size = baseSize;
1022 int const* constFds = static_cast<int const*>(baseFds.get());
1023 numFds = baseNumFds;
1024 if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
1025 return false;
1026 }
1027
1028 return true;
1029 }
1030
1031 // Ref: frameworks/native/libs/ui/Region.cpp
1032
1033 /**
1034 * \brief Return the size of the buffer required to flatten `Region`.
1035 *
1036 * \param[in] t The input `Region`.
1037 * \return The required size of the flat buffer.
1038 */
getFlattenedSize(Region const & t)1039 size_t getFlattenedSize(Region const& t) {
1040 return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
1041 }
1042
1043 /**
1044 * \brief Unflatten `Region`.
1045 *
1046 * \param[out] t The destination `Region`.
1047 * \param[in,out] buffer The pointer to the flat buffer.
1048 * \param[in,out] size The size of the flat buffer.
1049 * \return `NO_ERROR` on success; other value on failure.
1050 */
unflatten(Region * t,void const * & buffer,size_t & size)1051 status_t unflatten(Region* t, void const*& buffer, size_t& size) {
1052 if (size < sizeof(uint32_t)) {
1053 return NO_MEMORY;
1054 }
1055
1056 uint32_t numRects = 0;
1057 FlattenableUtils::read(buffer, size, numRects);
1058 if (size < numRects * sizeof(Rect)) {
1059 return NO_MEMORY;
1060 }
1061 if (numRects > (UINT32_MAX / sizeof(Rect))) {
1062 return NO_MEMORY;
1063 }
1064
1065 t->resize(numRects);
1066 for (size_t r = 0; r < numRects; ++r) {
1067 ::android::Rect rect(::android::Rect::EMPTY_RECT);
1068 status_t status = rect.unflatten(buffer, size);
1069 if (status != NO_ERROR) {
1070 return status;
1071 }
1072 FlattenableUtils::advance(buffer, size, sizeof(rect));
1073 (*t)[r] = Rect{
1074 static_cast<int32_t>(rect.left),
1075 static_cast<int32_t>(rect.top),
1076 static_cast<int32_t>(rect.right),
1077 static_cast<int32_t>(rect.bottom)};
1078 }
1079 return NO_ERROR;
1080 }
1081
1082 /**
1083 * \brief Flatten `Region`.
1084 *
1085 * \param[in] t The source `Region`.
1086 * \param[in,out] buffer The pointer to the flat buffer.
1087 * \param[in,out] size The size of the flat buffer.
1088 * \return `NO_ERROR` on success; other value on failure.
1089 */
flatten(Region const & t,void * & buffer,size_t & size)1090 status_t flatten(Region const& t, void*& buffer, size_t& size) {
1091 if (size < getFlattenedSize(t)) {
1092 return NO_MEMORY;
1093 }
1094
1095 FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
1096 for (size_t r = 0; r < t.size(); ++r) {
1097 ::android::Rect rect(
1098 static_cast<int32_t>(t[r].left),
1099 static_cast<int32_t>(t[r].top),
1100 static_cast<int32_t>(t[r].right),
1101 static_cast<int32_t>(t[r].bottom));
1102 status_t status = rect.flatten(buffer, size);
1103 if (status != NO_ERROR) {
1104 return status;
1105 }
1106 FlattenableUtils::advance(buffer, size, sizeof(rect));
1107 }
1108 return NO_ERROR;
1109 }
1110
1111 /**
1112 * \brief Convert `::android::Region` to `Region`.
1113 *
1114 * \param[out] t The destination `Region`.
1115 * \param[in] l The source `::android::Region`.
1116 */
1117 // convert: ::android::Region -> Region
convertTo(Region * t,::android::Region const & l)1118 bool convertTo(Region* t, ::android::Region const& l) {
1119 size_t const baseSize = l.getFlattenedSize();
1120 std::unique_ptr<uint8_t[]> baseBuffer(
1121 new (std::nothrow) uint8_t[baseSize]);
1122 if (!baseBuffer) {
1123 return false;
1124 }
1125
1126 void* buffer = static_cast<void*>(baseBuffer.get());
1127 size_t size = baseSize;
1128 if (l.flatten(buffer, size) != NO_ERROR) {
1129 return false;
1130 }
1131
1132 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1133 size = baseSize;
1134 if (unflatten(t, constBuffer, size) != NO_ERROR) {
1135 return false;
1136 }
1137
1138 return true;
1139 }
1140
1141 /**
1142 * \brief Convert `Region` to `::android::Region`.
1143 *
1144 * \param[out] l The destination `::android::Region`.
1145 * \param[in] t The source `Region`.
1146 */
1147 // convert: Region -> ::android::Region
convertTo(::android::Region * l,Region const & t)1148 bool convertTo(::android::Region* l, Region const& t) {
1149 size_t const baseSize = getFlattenedSize(t);
1150 std::unique_ptr<uint8_t[]> baseBuffer(
1151 new (std::nothrow) uint8_t[baseSize]);
1152 if (!baseBuffer) {
1153 return false;
1154 }
1155
1156 void* buffer = static_cast<void*>(baseBuffer.get());
1157 size_t size = baseSize;
1158 if (flatten(t, buffer, size) != NO_ERROR) {
1159 return false;
1160 }
1161
1162 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1163 size = baseSize;
1164 if (l->unflatten(constBuffer, size) != NO_ERROR) {
1165 return false;
1166 }
1167
1168 return true;
1169 }
1170
1171 // Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
1172 // BGraphicBufferProducer::QueueBufferInput
1173
1174 /**
1175 * \brief Return a lower bound on the size of the buffer required to flatten
1176 * `HGraphicBufferProducer::QueueBufferInput`.
1177 *
1178 * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
1179 * \return A lower bound on the size of the flat buffer.
1180 */
minFlattenedSize(HGraphicBufferProducer::QueueBufferInput const &)1181 constexpr size_t minFlattenedSize(
1182 HGraphicBufferProducer::QueueBufferInput const& /* t */) {
1183 return sizeof(int64_t) + // timestamp
1184 sizeof(int) + // isAutoTimestamp
1185 sizeof(android_dataspace) + // dataSpace
1186 sizeof(::android::Rect) + // crop
1187 sizeof(int) + // scalingMode
1188 sizeof(uint32_t) + // transform
1189 sizeof(uint32_t) + // stickyTransform
1190 sizeof(bool) + // getFrameTimestamps
1191 sizeof(int); // slot
1192 }
1193
1194 /**
1195 * \brief Return the size of the buffer required to flatten
1196 * `HGraphicBufferProducer::QueueBufferInput`.
1197 *
1198 * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
1199 * \return The required size of the flat buffer.
1200 */
getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const & t)1201 size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
1202 return minFlattenedSize(t) +
1203 getFenceFlattenedSize(t.fence) +
1204 getFlattenedSize(t.surfaceDamage) +
1205 sizeof(HdrMetadata::validTypes);
1206 }
1207
1208 /**
1209 * \brief Return the number of file descriptors contained in
1210 * `HGraphicBufferProducer::QueueBufferInput`.
1211 *
1212 * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
1213 * \return The number of file descriptors contained in \p t.
1214 */
getFdCount(HGraphicBufferProducer::QueueBufferInput const & t)1215 size_t getFdCount(
1216 HGraphicBufferProducer::QueueBufferInput const& t) {
1217 return getFenceFdCount(t.fence);
1218 }
1219
1220 /**
1221 * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
1222 *
1223 * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
1224 * \param[out] nh The native handle cloned from `t.fence`.
1225 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1226 * \param[in,out] size The size of the flat non-fd buffer.
1227 * \param[in,out] fds The pointer to the flat fd buffer.
1228 * \param[in,out] numFds The size of the flat fd buffer.
1229 * \return `NO_ERROR` on success; other value on failure.
1230 *
1231 * 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)1232 status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
1233 native_handle_t** nh,
1234 void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1235 if (size < getFlattenedSize(t)) {
1236 return NO_MEMORY;
1237 }
1238
1239 FlattenableUtils::write(buffer, size, t.timestamp);
1240 FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
1241 FlattenableUtils::write(buffer, size,
1242 static_cast<android_dataspace_t>(t.dataSpace));
1243 FlattenableUtils::write(buffer, size, ::android::Rect(
1244 static_cast<int32_t>(t.crop.left),
1245 static_cast<int32_t>(t.crop.top),
1246 static_cast<int32_t>(t.crop.right),
1247 static_cast<int32_t>(t.crop.bottom)));
1248 FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
1249 FlattenableUtils::write(buffer, size, t.transform);
1250 FlattenableUtils::write(buffer, size, t.stickyTransform);
1251 FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
1252
1253 *nh = t.fence.getNativeHandle() == nullptr ?
1254 nullptr : native_handle_clone(t.fence);
1255 status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
1256 if (status != NO_ERROR) {
1257 return status;
1258 }
1259 status = flatten(t.surfaceDamage, buffer, size);
1260 if (status != NO_ERROR) {
1261 return status;
1262 }
1263 FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
1264 FlattenableUtils::write(buffer, size, -1 /*slot*/);
1265 return NO_ERROR;
1266 }
1267
1268 /**
1269 * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
1270 *
1271 * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
1272 * \param[out] nh The underlying native handle for `t->fence`.
1273 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1274 * \param[in,out] size The size of the flat non-fd buffer.
1275 * \param[in,out] fds The pointer to the flat fd buffer.
1276 * \param[in,out] numFds The size of the flat fd buffer.
1277 * \return `NO_ERROR` on success; other value on failure.
1278 *
1279 * If the return value is `NO_ERROR` and `t->fence` contains a valid file
1280 * descriptor, \p nh will be a newly created native handle holding that file
1281 * descriptor. \p nh needs to be deleted with `native_handle_delete()`
1282 * afterwards.
1283 */
unflatten(HGraphicBufferProducer::QueueBufferInput * t,native_handle_t ** nh,void const * & buffer,size_t & size,int const * & fds,size_t & numFds)1284 status_t unflatten(
1285 HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
1286 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1287 if (size < minFlattenedSize(*t)) {
1288 return NO_MEMORY;
1289 }
1290
1291 FlattenableUtils::read(buffer, size, t->timestamp);
1292 int lIsAutoTimestamp;
1293 FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
1294 t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
1295 android_dataspace_t lDataSpace;
1296 FlattenableUtils::read(buffer, size, lDataSpace);
1297 t->dataSpace = static_cast<Dataspace>(lDataSpace);
1298 Rect lCrop;
1299 FlattenableUtils::read(buffer, size, lCrop);
1300 t->crop = Rect{
1301 static_cast<int32_t>(lCrop.left),
1302 static_cast<int32_t>(lCrop.top),
1303 static_cast<int32_t>(lCrop.right),
1304 static_cast<int32_t>(lCrop.bottom)};
1305 int lScalingMode;
1306 FlattenableUtils::read(buffer, size, lScalingMode);
1307 t->scalingMode = static_cast<int32_t>(lScalingMode);
1308 FlattenableUtils::read(buffer, size, t->transform);
1309 FlattenableUtils::read(buffer, size, t->stickyTransform);
1310 FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
1311
1312 status_t status = unflattenFence(&(t->fence), nh,
1313 buffer, size, fds, numFds);
1314 if (status != NO_ERROR) {
1315 return status;
1316 }
1317 // HdrMetadata and slot ignored
1318 return unflatten(&(t->surfaceDamage), buffer, size);
1319 }
1320
1321
1322 /**
1323 * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
1324 * `BGraphicBufferProducer::QueueBufferInput`.
1325 *
1326 * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
1327 * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
1328 *
1329 * If `t.fence` has a valid file descriptor, it will be duplicated.
1330 */
convertTo(BGraphicBufferProducer::QueueBufferInput * l,HGraphicBufferProducer::QueueBufferInput const & t)1331 bool convertTo(
1332 BGraphicBufferProducer::QueueBufferInput* l,
1333 HGraphicBufferProducer::QueueBufferInput const& t) {
1334
1335 size_t const baseSize = getFlattenedSize(t);
1336 std::unique_ptr<uint8_t[]> baseBuffer(
1337 new (std::nothrow) uint8_t[baseSize]);
1338 if (!baseBuffer) {
1339 return false;
1340 }
1341
1342 size_t const baseNumFds = getFdCount(t);
1343 std::unique_ptr<int[]> baseFds(
1344 new (std::nothrow) int[baseNumFds]);
1345 if (!baseFds) {
1346 return false;
1347 }
1348
1349 void* buffer = static_cast<void*>(baseBuffer.get());
1350 size_t size = baseSize;
1351 int* fds = baseFds.get();
1352 size_t numFds = baseNumFds;
1353 native_handle_t* nh;
1354 if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
1355 return false;
1356 }
1357
1358 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1359 size = baseSize;
1360 int const* constFds = static_cast<int const*>(baseFds.get());
1361 numFds = baseNumFds;
1362 if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
1363 if (nh != nullptr) {
1364 native_handle_close(nh);
1365 native_handle_delete(nh);
1366 }
1367 return false;
1368 }
1369
1370 native_handle_delete(nh);
1371 return true;
1372 }
1373
1374 // Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
1375 // BGraphicBufferProducer::QueueBufferOutput
1376
1377 /**
1378 * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
1379 * `HGraphicBufferProducer::QueueBufferOutput`.
1380 *
1381 * \param[out] t The wrapper of type
1382 * `HGraphicBufferProducer::QueueBufferOutput`.
1383 * \param[out] nh The array of array of native handles that are referred to by
1384 * members of \p t.
1385 * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
1386 *
1387 * On success, each member of \p nh will be either `nullptr` or a newly created
1388 * native handle. All the non-`nullptr` elements must be deleted individually
1389 * with `native_handle_delete()`.
1390 */
1391 // wrap: BGraphicBufferProducer::QueueBufferOutput ->
1392 // HGraphicBufferProducer::QueueBufferOutput
wrapAs(HGraphicBufferProducer::QueueBufferOutput * t,std::vector<std::vector<native_handle_t * >> * nh,BGraphicBufferProducer::QueueBufferOutput const & l)1393 bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
1394 std::vector<std::vector<native_handle_t*> >* nh,
1395 BGraphicBufferProducer::QueueBufferOutput const& l) {
1396 if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
1397 return false;
1398 }
1399 t->width = l.width;
1400 t->height = l.height;
1401 t->transformHint = l.transformHint;
1402 t->numPendingBuffers = l.numPendingBuffers;
1403 t->nextFrameNumber = l.nextFrameNumber;
1404 t->bufferReplaced = l.bufferReplaced;
1405 return true;
1406 }
1407
1408 /**
1409 * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
1410 * `BGraphicBufferProducer::QueueBufferOutput`.
1411 *
1412 * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
1413 * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
1414 *
1415 * This function will duplicate all file descriptors contained in \p t.
1416 */
1417 // convert: HGraphicBufferProducer::QueueBufferOutput ->
1418 // BGraphicBufferProducer::QueueBufferOutput
convertTo(BGraphicBufferProducer::QueueBufferOutput * l,HGraphicBufferProducer::QueueBufferOutput const & t)1419 bool convertTo(
1420 BGraphicBufferProducer::QueueBufferOutput* l,
1421 HGraphicBufferProducer::QueueBufferOutput const& t) {
1422 if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
1423 return false;
1424 }
1425 l->width = t.width;
1426 l->height = t.height;
1427 l->transformHint = t.transformHint;
1428 l->numPendingBuffers = t.numPendingBuffers;
1429 l->nextFrameNumber = t.nextFrameNumber;
1430 l->bufferReplaced = t.bufferReplaced;
1431 return true;
1432 }
1433
1434 /**
1435 * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
1436 * `HGraphicBufferProducer::DisconnectMode`.
1437 *
1438 * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
1439 * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
1440 */
toHidlDisconnectMode(BGraphicBufferProducer::DisconnectMode l)1441 HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
1442 BGraphicBufferProducer::DisconnectMode l) {
1443 switch (l) {
1444 case BGraphicBufferProducer::DisconnectMode::Api:
1445 return HGraphicBufferProducer::DisconnectMode::API;
1446 case BGraphicBufferProducer::DisconnectMode::AllLocal:
1447 return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
1448 }
1449 return HGraphicBufferProducer::DisconnectMode::API;
1450 }
1451
1452 /**
1453 * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
1454 * `BGraphicBufferProducer::DisconnectMode`.
1455 *
1456 * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
1457 * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
1458 */
toGuiDisconnectMode(HGraphicBufferProducer::DisconnectMode t)1459 BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
1460 HGraphicBufferProducer::DisconnectMode t) {
1461 switch (t) {
1462 case HGraphicBufferProducer::DisconnectMode::API:
1463 return BGraphicBufferProducer::DisconnectMode::Api;
1464 case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
1465 return BGraphicBufferProducer::DisconnectMode::AllLocal;
1466 }
1467 return BGraphicBufferProducer::DisconnectMode::Api;
1468 }
1469
1470 } // namespace conversion
1471 } // namespace android
1472
1473