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