blob: f3f8441ed9d2d7ff1cc36e26c1456eaca9fa0cbf [file] [log] [blame]
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001/*
2 * Copyright 2016, 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#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
18#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
19
Pawin Vongmasa0d3a5ed2017-02-22 03:19:35 -080020#include <vector>
21#include <list>
22
23#include <unistd.h>
24
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -080025#include <hidl/MQDescriptor.h>
26#include <hidl/Status.h>
27#include <hidlmemory/mapping.h>
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -080028
29#include <binder/Binder.h>
30#include <binder/Status.h>
31#include <ui/FenceTime.h>
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -080032#include <cutils/native_handle.h>
33#include <gui/IGraphicBufferProducer.h>
34
Pawin Vongmasaac7d4122017-03-01 05:48:42 -080035#include <media/OMXFenceParcelable.h>
Pawin Vongmasa0d3a5ed2017-02-22 03:19:35 -080036#include <media/OMXBuffer.h>
Pawin Vongmasaac7d4122017-03-01 05:48:42 -080037#include <media/hardware/VideoAPI.h>
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -080038
Pawin Vongmasa0d3a5ed2017-02-22 03:19:35 -080039#include <android/hidl/memory/1.0/IMemory.h>
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -080040#include <android/hardware/media/omx/1.0/types.h>
41#include <android/hardware/media/omx/1.0/IOmx.h>
42#include <android/hardware/media/omx/1.0/IOmxNode.h>
43#include <android/hardware/media/omx/1.0/IOmxBufferProducer.h>
44#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
45#include <android/hardware/media/omx/1.0/IOmxObserver.h>
46#include <android/hardware/media/omx/1.0/IOmxProducerListener.h>
47#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
48
Pawin Vongmasa0d3a5ed2017-02-22 03:19:35 -080049#include <android/IGraphicBufferSource.h>
50#include <android/IOMXBufferSource.h>
51
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -080052namespace android {
53namespace hardware {
54namespace media {
55namespace omx {
56namespace V1_0 {
57namespace utils {
58
59using ::android::hardware::hidl_array;
60using ::android::hardware::hidl_string;
61using ::android::hardware::hidl_vec;
62using ::android::hardware::hidl_handle;
63using ::android::hardware::Return;
64using ::android::hardware::Void;
65using ::android::sp;
66
67using ::android::String8;
68using ::android::OMXFenceParcelable;
69
70using ::android::hardware::media::omx::V1_0::Message;
71using ::android::omx_message;
72
73using ::android::hardware::media::omx::V1_0::ColorAspects;
74using ::android::hardware::media::V1_0::Rect;
75using ::android::hardware::media::V1_0::Region;
76
77using ::android::hardware::graphics::common::V1_0::Dataspace;
78
79using ::android::hardware::graphics::common::V1_0::PixelFormat;
80
81using ::android::OMXBuffer;
82
83using ::android::hardware::media::V1_0::AnwBuffer;
84using ::android::GraphicBuffer;
85
86using ::android::hardware::media::omx::V1_0::IOmx;
87using ::android::IOMX;
88
89using ::android::hardware::media::omx::V1_0::IOmxNode;
90using ::android::IOMXNode;
91
92using ::android::hardware::media::omx::V1_0::IOmxObserver;
93using ::android::IOMXObserver;
94
95using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
96using ::android::IOMXBufferSource;
97
98using ::android::hardware::media::omx::V1_0::IOmxBufferProducer;
99using ::android::IGraphicBufferProducer;
100
101// native_handle_t helper functions.
102
103/**
104 * \brief Take an fd and create a native handle containing only the given fd.
105 * The created handle will need to be deleted manually with
106 * `native_handle_delete()`.
107 *
108 * \param[in] fd The source file descriptor (of type `int`).
109 * \return The create `native_handle_t*` that contains the given \p fd. If the
110 * supplied \p fd is negative, the created native handle will contain no file
111 * descriptors.
112 *
113 * If the native handle cannot be created, the return value will be
114 * `nullptr`.
115 *
116 * This function does not duplicate the file descriptor.
117 */
118inline native_handle_t* native_handle_create_from_fd(int fd) {
119 if (fd < 0) {
120 return native_handle_create(0, 0);
121 }
122 native_handle_t* nh = native_handle_create(1, 0);
123 if (nh == nullptr) {
124 return nullptr;
125 }
126 nh->data[0] = fd;
127 return nh;
128}
129
130/**
131 * \brief Extract a file descriptor from a native handle.
132 *
133 * \param[in] nh The source `native_handle_t*`.
134 * \param[in] index The index of the file descriptor in \p nh to read from. This
135 * input has the default value of `0`.
136 * \return The `index`-th file descriptor in \p nh. If \p nh does not have
137 * enough file descriptors, the returned value will be `-1`.
138 *
139 * This function does not duplicate the file descriptor.
140 */
141inline int native_handle_read_fd(native_handle_t const* nh, int index = 0) {
142 return ((nh == nullptr) || (nh->numFds == 0) ||
143 (nh->numFds <= index) || (index < 0)) ?
144 -1 : nh->data[index];
145}
146
147/**
148 * Conversion functions
149 * ====================
150 *
151 * There are two main directions of conversion:
152 * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
153 * input. The wrapper has type `TargetType`.
154 * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
155 * corresponds to the input. The lifetime of the output does not depend on the
156 * lifetime of the input.
157 * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
158 * that cannot be copied and/or moved efficiently, or when there are multiple
159 * output arguments.
160 * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
161 * `TargetType` that cannot be copied and/or moved efficiently, or when there
162 * are multiple output arguments.
163 *
164 * `wrapIn()` and `convertTo()` functions will take output arguments before
165 * input arguments. Some of these functions might return a value to indicate
166 * success or error.
167 *
168 * In converting or wrapping something as a Treble type that contains a
169 * `hidl_handle`, `native_handle_t*` will need to be created and returned as
170 * an additional output argument, hence only `wrapIn()` or `convertTo()` would
171 * be available. The caller must call `native_handle_delete()` to deallocate the
172 * returned native handle when it is no longer needed.
173 *
174 * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
175 * not perform duplication of file descriptors, while `toTargetType()` and
176 * `convertTo()` do.
177 */
178
179/**
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800180 * \brief Convert `Return<void>` to `binder::Status`.
181 *
182 * \param[in] t The source `Return<void>`.
183 * \return The corresponding `binder::Status`.
184 */
185// convert: Return<void> -> ::android::binder::Status
186inline ::android::binder::Status toBinderStatus(
187 Return<void> const& t) {
188 return ::android::binder::Status::fromExceptionCode(
189 t.isOk() ? OK : UNKNOWN_ERROR,
190 t.description().c_str());
191}
192
193/**
Robert Shih3d32c952017-02-23 12:09:30 -0800194 * \brief Convert `Return<Status>` to `binder::Status`.
195 *
196 * \param[in] t The source `Return<Status>`.
197 * \return The corresponding `binder::Status`.
198 */
199// convert: Return<Status> -> ::android::binder::Status
200inline ::android::binder::Status toBinderStatus(
201 Return<Status> const& t) {
202 return ::android::binder::Status::fromStatusT(
203 t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR);
204}
205
206/**
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800207 * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder
208 * calls.
209 *
210 * \param[in] t The source `Return<Status>`.
211 * \return The corresponding `status_t`.
212 *
213 * This function first check if \p t has a transport error. If it does, then the
214 * return value is the transport error code. Otherwise, the return value is
215 * converted from `Status` contained inside \p t.
216 *
217 * Note:
218 * - This `Status` is omx-specific. It is defined in `types.hal`.
219 * - The name of this function is not `convert`.
220 */
221// convert: Status -> status_t
222inline status_t toStatusT(Return<Status> const& t) {
223 return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR;
224}
225
226/**
227 * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
228 *
229 * \param[in] t The source `Return<void>`.
230 * \return The corresponding `status_t`.
231 */
232// convert: Return<void> -> status_t
233inline status_t toStatusT(Return<void> const& t) {
234 return t.isOk() ? OK : UNKNOWN_ERROR;
235}
236
237/**
238 * \brief Convert `Status` to `status_t`. This is for legacy binder calls.
239 *
240 * \param[in] t The source `Status`.
241 * \return the corresponding `status_t`.
242 */
243// convert: Status -> status_t
244inline status_t toStatusT(Status const& t) {
245 return static_cast<status_t>(t);
246}
247
248/**
249 * \brief Convert `status_t` to `Status`.
250 *
251 * \param[in] l The source `status_t`.
252 * \return The corresponding `Status`.
253 */
254// convert: status_t -> Status
255inline Status toStatus(status_t l) {
256 return static_cast<Status>(l);
257}
258
259/**
260 * \brief Wrap `native_handle_t*` in `hidl_handle`.
261 *
262 * \param[in] nh The source `native_handle_t*`.
263 * \return The `hidl_handle` that points to \p nh.
264 */
265// wrap: native_handle_t* -> hidl_handle
266inline hidl_handle inHidlHandle(native_handle_t const* nh) {
267 return hidl_handle(nh);
268}
269
270/**
271 * \brief Wrap an `omx_message` and construct the corresponding `Message`.
272 *
273 * \param[out] t The wrapper of type `Message`.
274 * \param[out] nh The native_handle_t referred to by `t->fence`.
275 * \param[in] l The source `omx_message`.
276 * \return `true` if the wrapping is successful; `false` otherwise.
277 *
278 * Upon success, \p nh will be created to hold the file descriptor stored in
279 * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be
280 * destroyed manually by `native_handle_delete()` when \p t is no longer needed.
281 *
282 * Upon failure, \p nh will not be created and will not need to be deleted. \p t
283 * will be invalid.
284 */
285// wrap, omx_message -> Message, native_handle_t*
286inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) {
287 *nh = native_handle_create_from_fd(l.fenceFd);
288 if (!*nh) {
289 return false;
290 }
Pawin Vongmasa8ff40182017-02-07 02:22:34 -0800291 t->fence = *nh;
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800292 switch (l.type) {
293 case omx_message::EVENT:
294 t->type = Message::Type::EVENT;
Pawin Vongmasa8a21c012016-12-27 04:30:54 +0700295 t->data.eventData.event = uint32_t(l.u.event_data.event);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800296 t->data.eventData.data1 = l.u.event_data.data1;
297 t->data.eventData.data2 = l.u.event_data.data2;
298 t->data.eventData.data3 = l.u.event_data.data3;
299 t->data.eventData.data4 = l.u.event_data.data4;
300 break;
301 case omx_message::EMPTY_BUFFER_DONE:
302 t->type = Message::Type::EMPTY_BUFFER_DONE;
303 t->data.bufferData.buffer = l.u.buffer_data.buffer;
304 break;
305 case omx_message::FILL_BUFFER_DONE:
306 t->type = Message::Type::FILL_BUFFER_DONE;
307 t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer;
308 t->data.extendedBufferData.rangeOffset =
309 l.u.extended_buffer_data.range_offset;
310 t->data.extendedBufferData.rangeLength =
311 l.u.extended_buffer_data.range_length;
312 t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags;
313 t->data.extendedBufferData.timestampUs =
314 l.u.extended_buffer_data.timestamp;
315 break;
316 case omx_message::FRAME_RENDERED:
317 t->type = Message::Type::FRAME_RENDERED;
318 t->data.renderData.timestampUs = l.u.render_data.timestamp;
319 t->data.renderData.systemTimeNs = l.u.render_data.nanoTime;
320 break;
321 default:
322 native_handle_delete(*nh);
323 return false;
324 }
325 return true;
326}
327
328/**
329 * \brief Wrap a `Message` inside an `omx_message`.
330 *
331 * \param[out] l The wrapper of type `omx_message`.
332 * \param[in] t The source `Message`.
333 * \return `true` if the wrapping is successful; `false` otherwise.
334 */
335// wrap: Message -> omx_message
336inline bool wrapAs(omx_message* l, Message const& t) {
337 l->fenceFd = native_handle_read_fd(t.fence);
338 switch (t.type) {
339 case Message::Type::EVENT:
340 l->type = omx_message::EVENT;
Pawin Vongmasa8a21c012016-12-27 04:30:54 +0700341 l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800342 l->u.event_data.data1 = t.data.eventData.data1;
343 l->u.event_data.data2 = t.data.eventData.data2;
344 l->u.event_data.data3 = t.data.eventData.data3;
345 l->u.event_data.data4 = t.data.eventData.data4;
346 break;
347 case Message::Type::EMPTY_BUFFER_DONE:
348 l->type = omx_message::EMPTY_BUFFER_DONE;
349 l->u.buffer_data.buffer = t.data.bufferData.buffer;
350 break;
351 case Message::Type::FILL_BUFFER_DONE:
352 l->type = omx_message::FILL_BUFFER_DONE;
353 l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer;
354 l->u.extended_buffer_data.range_offset =
355 t.data.extendedBufferData.rangeOffset;
356 l->u.extended_buffer_data.range_length =
357 t.data.extendedBufferData.rangeLength;
358 l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags;
359 l->u.extended_buffer_data.timestamp =
360 t.data.extendedBufferData.timestampUs;
361 break;
362 case Message::Type::FRAME_RENDERED:
363 l->type = omx_message::FRAME_RENDERED;
364 l->u.render_data.timestamp = t.data.renderData.timestampUs;
365 l->u.render_data.nanoTime = t.data.renderData.systemTimeNs;
366 break;
367 default:
368 return false;
369 }
370 return true;
371}
372
373/**
374 * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will
375 * have an extended lifetime.
376 *
377 * \param[out] l The output `omx_message`.
378 * \param[in] t The source `Message`.
379 * \return `true` if the conversion is successful; `false` otherwise.
380 *
381 * This function calls `wrapto()`, then attempts to duplicate the file
382 * descriptor for the fence if it is not `-1`. If duplication fails, `false`
383 * will be returned.
384 */
385// convert: Message -> omx_message
386inline bool convertTo(omx_message* l, Message const& t) {
387 if (!wrapAs(l, t)) {
388 return false;
389 }
390 if (l->fenceFd == -1) {
391 return true;
392 }
393 l->fenceFd = dup(l->fenceFd);
394 return l->fenceFd != -1;
395}
396
397/**
398 * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`.
399 *
400 * \param[out] t The wrapper of type `hidl_handle`.
401 * \param[out] nh The native handle created to hold the file descriptor inside
402 * \p l.
403 * \param[in] l The source `OMXFenceParcelable`, which essentially contains one
404 * file descriptor.
405 * \return `true` if \p t and \p nh are successfully created to wrap around \p
406 * l; `false` otherwise.
407 *
408 * On success, \p nh needs to be deleted by the caller with
409 * `native_handle_delete()` after \p t and \p nh are no longer needed.
410 *
411 * On failure, \p nh will not need to be deleted, and \p t will hold an invalid
412 * value.
413 */
414// wrap: OMXFenceParcelable -> hidl_handle, native_handle_t*
415inline bool wrapAs(hidl_handle* t, native_handle_t** nh,
416 OMXFenceParcelable const& l) {
417 *nh = native_handle_create_from_fd(l.get());
418 if (!*nh) {
419 return false;
420 }
421 *t = *nh;
422 return true;
423}
424
425/**
426 * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`.
427 *
428 * \param[out] l The wrapper of type `OMXFenceParcelable`.
429 * \param[in] t The source `hidl_handle`.
430 */
431// wrap: hidl_handle -> OMXFenceParcelable
432inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) {
433 l->mFenceFd = native_handle_read_fd(t);
434}
435
436/**
437 * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle`
438 * contains file descriptors, the first file descriptor will be duplicated and
439 * stored in the output `OMXFenceParcelable`.
440 *
441 * \param[out] l The output `OMXFenceParcelable`.
442 * \param[in] t The input `hidl_handle`.
443 * \return `false` if \p t contains a valid file descriptor but duplication
444 * fails; `true` otherwise.
445 */
446// convert: hidl_handle -> OMXFenceParcelable
447inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) {
448 int fd = native_handle_read_fd(t);
449 if (fd != -1) {
450 fd = dup(fd);
451 if (fd == -1) {
452 return false;
453 }
454 }
455 l->mFenceFd = fd;
456 return true;
457}
458
459/**
460 * \brief Convert `::android::ColorAspects` to `ColorAspects`.
461 *
462 * \param[in] l The source `::android::ColorAspects`.
463 * \return The corresponding `ColorAspects`.
464 */
465// convert: ::android::ColorAspects -> ColorAspects
466inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) {
467 return ColorAspects{
468 static_cast<ColorAspects::Range>(l.mRange),
469 static_cast<ColorAspects::Primaries>(l.mPrimaries),
470 static_cast<ColorAspects::Transfer>(l.mTransfer),
471 static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)};
472}
473
474/**
475 * \brief Convert `int32_t` to `ColorAspects`.
476 *
477 * \param[in] l The source `int32_t`.
478 * \return The corresponding `ColorAspects`.
479 */
480// convert: int32_t -> ColorAspects
481inline ColorAspects toHardwareColorAspects(int32_t l) {
482 return ColorAspects{
483 static_cast<ColorAspects::Range>((l >> 24) & 0xFF),
484 static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF),
485 static_cast<ColorAspects::Transfer>(l & 0xFF),
486 static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)};
487}
488
489/**
490 * \brief Convert `ColorAspects` to `::android::ColorAspects`.
491 *
492 * \param[in] t The source `ColorAspects`.
493 * \return The corresponding `::android::ColorAspects`.
494 */
495// convert: ColorAspects -> ::android::ColorAspects
496inline int32_t toCompactColorAspects(ColorAspects const& t) {
497 return static_cast<int32_t>(
498 (static_cast<uint32_t>(t.range) << 24) |
499 (static_cast<uint32_t>(t.primaries) << 16) |
500 (static_cast<uint32_t>(t.transfer)) |
501 (static_cast<uint32_t>(t.matrixCoeffs) << 8));
502}
503
504/**
505 * \brief Convert `int32_t` to `Dataspace`.
506 *
507 * \param[in] l The source `int32_t`.
508 * \result The corresponding `Dataspace`.
509 */
510// convert: int32_t -> Dataspace
511inline Dataspace toHardwareDataspace(int32_t l) {
512 return static_cast<Dataspace>(l);
513}
514
515/**
516 * \brief Convert `Dataspace` to `int32_t`.
517 *
518 * \param[in] t The source `Dataspace`.
519 * \result The corresponding `int32_t`.
520 */
521// convert: Dataspace -> int32_t
522inline int32_t toRawDataspace(Dataspace const& t) {
523 return static_cast<int32_t>(t);
524}
525
526/**
527 * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
528 *
529 * \param[in] l The pointer to the beginning of the opaque buffer.
530 * \param[in] size The size of the buffer.
531 * \return A `hidl_vec<uint8_t>` that points to the buffer.
532 */
533// wrap: void*, size_t -> hidl_vec<uint8_t>
534inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
535 hidl_vec<uint8_t> t;
536 t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
537 return t;
538}
539
540/**
541 * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
542 *
543 * \param[in] l The pointer to the beginning of the opaque buffer.
544 * \param[in] size The size of the buffer.
545 * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
546 */
547// convert: void*, size_t -> hidl_vec<uint8_t>
548inline hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
549 hidl_vec<uint8_t> t;
550 t.resize(size);
551 uint8_t const* src = static_cast<uint8_t const*>(l);
552 std::copy(src, src + size, t.data());
553 return t;
554}
555
556/**
Pawin Vongmasa9c47c972017-02-08 04:09:38 -0800557 * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
558 *
559 * \param[out] t The wrapper of type `AnwBuffer`.
560 * \param[in] l The source `GraphicBuffer`.
561 */
562// wrap: GraphicBuffer -> AnwBuffer
563inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
564 t->attr.width = l.getWidth();
565 t->attr.height = l.getHeight();
566 t->attr.stride = l.getStride();
567 t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
568 t->attr.layerCount = l.getLayerCount();
569 t->attr.usage = l.getUsage();
570 t->attr.id = l.getId();
571 t->attr.generationNumber = l.getGenerationNumber();
572 t->nativeHandle = hidl_handle(l.handle);
573}
574
575/**
576 * \brief Convert `AnwBuffer` to `GraphicBuffer`.
577 *
578 * \param[out] l The destination `GraphicBuffer`.
579 * \param[in] t The source `AnwBuffer`.
580 *
581 * This function will duplicate all file descriptors in \p t.
582 */
583// convert: AnwBuffer -> GraphicBuffer
584// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
585inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
586 native_handle_t* handle = t.nativeHandle == nullptr ?
587 nullptr : native_handle_clone(t.nativeHandle);
588
589 size_t const numInts = 12 + (handle ? handle->numInts : 0);
590 int32_t* ints = new int32_t[numInts];
591
592 size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
593 int* fds = new int[numFds];
594
595 ints[0] = 'GBFR';
596 ints[1] = static_cast<int32_t>(t.attr.width);
597 ints[2] = static_cast<int32_t>(t.attr.height);
598 ints[3] = static_cast<int32_t>(t.attr.stride);
599 ints[4] = static_cast<int32_t>(t.attr.format);
600 ints[5] = static_cast<int32_t>(t.attr.layerCount);
601 ints[6] = static_cast<int32_t>(t.attr.usage);
602 ints[7] = static_cast<int32_t>(t.attr.id >> 32);
603 ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
604 ints[9] = static_cast<int32_t>(t.attr.generationNumber);
605 ints[10] = 0;
606 ints[11] = 0;
607 if (handle) {
608 ints[10] = static_cast<int32_t>(handle->numFds);
609 ints[11] = static_cast<int32_t>(handle->numInts);
610 int* intsStart = handle->data + handle->numFds;
611 std::copy(handle->data, intsStart, fds);
612 std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
613 }
614
615 void const* constBuffer = static_cast<void const*>(ints);
616 size_t size = numInts * sizeof(int32_t);
617 int const* constFds = static_cast<int const*>(fds);
618 status_t status = l->unflatten(constBuffer, size, constFds, numFds);
619
620 delete [] fds;
621 delete [] ints;
622 native_handle_delete(handle);
623 return status == NO_ERROR;
624}
625
626/**
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800627 * \brief Wrap `OMXBuffer` in `CodecBuffer`.
628 *
629 * \param[out] t The wrapper of type `CodecBuffer`.
630 * \param[in] l The source `OMXBuffer`.
631 * \return `true` if the wrapping is successful; `false` otherwise.
632 */
633// wrap: OMXBuffer -> CodecBuffer
634inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) {
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800635 t->sharedMemory = hidl_memory();
Pawin Vongmasa9c47c972017-02-08 04:09:38 -0800636 t->nativeHandle = hidl_handle();
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800637 switch (l.mBufferType) {
638 case OMXBuffer::kBufferTypeInvalid: {
639 t->type = CodecBuffer::Type::INVALID;
640 return true;
641 }
642 case OMXBuffer::kBufferTypePreset: {
643 t->type = CodecBuffer::Type::PRESET;
644 t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength);
645 t->attr.preset.rangeOffset = static_cast<uint32_t>(l.mRangeOffset);
646 return true;
647 }
648 case OMXBuffer::kBufferTypeHidlMemory: {
649 t->type = CodecBuffer::Type::SHARED_MEM;
650 t->sharedMemory = l.mHidlMemory;
651 return true;
652 }
653 case OMXBuffer::kBufferTypeSharedMem: {
654 // This is not supported.
655 return false;
656 }
657 case OMXBuffer::kBufferTypeANWBuffer: {
658 t->type = CodecBuffer::Type::ANW_BUFFER;
Pawin Vongmasa8ff40182017-02-07 02:22:34 -0800659 if (l.mGraphicBuffer == nullptr) {
660 t->attr.anwBuffer.width = 0;
661 t->attr.anwBuffer.height = 0;
662 t->attr.anwBuffer.stride = 0;
663 t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
664 t->attr.anwBuffer.layerCount = 0;
665 t->attr.anwBuffer.usage = 0;
Pawin Vongmasa8ff40182017-02-07 02:22:34 -0800666 return true;
667 }
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800668 t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
669 t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight();
670 t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride();
671 t->attr.anwBuffer.format = static_cast<PixelFormat>(
672 l.mGraphicBuffer->getPixelFormat());
673 t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount();
674 t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage();
Pawin Vongmasa9c47c972017-02-08 04:09:38 -0800675 t->nativeHandle = l.mGraphicBuffer->handle;
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800676 return true;
677 }
678 case OMXBuffer::kBufferTypeNativeHandle: {
679 t->type = CodecBuffer::Type::NATIVE_HANDLE;
Pawin Vongmasa9c47c972017-02-08 04:09:38 -0800680 t->nativeHandle = l.mNativeHandle->handle();
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800681 return true;
682 }
683 }
684 return false;
685}
686
687/**
688 * \brief Convert `CodecBuffer` to `OMXBuffer`.
689 *
690 * \param[out] l The destination `OMXBuffer`.
691 * \param[in] t The source `CodecBuffer`.
692 * \return `true` if successful; `false` otherwise.
693 */
694// convert: CodecBuffer -> OMXBuffer
695inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) {
696 switch (t.type) {
697 case CodecBuffer::Type::INVALID: {
698 *l = OMXBuffer();
699 return true;
700 }
701 case CodecBuffer::Type::PRESET: {
702 *l = OMXBuffer(
703 t.attr.preset.rangeOffset,
704 t.attr.preset.rangeLength);
705 return true;
706 }
707 case CodecBuffer::Type::SHARED_MEM: {
708 *l = OMXBuffer(t.sharedMemory);
709 return true;
710 }
711 case CodecBuffer::Type::ANW_BUFFER: {
Pawin Vongmasa8ff40182017-02-07 02:22:34 -0800712 if (t.nativeHandle.getNativeHandle() == nullptr) {
713 *l = OMXBuffer(sp<GraphicBuffer>(nullptr));
714 return true;
715 }
Pawin Vongmasa9c47c972017-02-08 04:09:38 -0800716 AnwBuffer anwBuffer;
717 anwBuffer.nativeHandle = t.nativeHandle;
718 anwBuffer.attr = t.attr.anwBuffer;
719 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
720 if (!convertTo(graphicBuffer.get(), anwBuffer)) {
721 return false;
722 }
723 *l = OMXBuffer(graphicBuffer);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800724 return true;
725 }
726 case CodecBuffer::Type::NATIVE_HANDLE: {
727 *l = OMXBuffer(NativeHandle::create(
728 native_handle_clone(t.nativeHandle), true));
729 return true;
730 }
731 }
732 return false;
733}
734
735/**
736 * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`.
737 *
738 * \param[out] t The destination `IOmx::ComponentInfo`.
739 * \param[in] l The source `IOMX::ComponentInfo`.
740 */
741// convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
742inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
743 t->mName = l.mName.string();
744 t->mRoles.resize(l.mRoles.size());
745 size_t i = 0;
746 for (auto& role : l.mRoles) {
747 t->mRoles[i++] = role.string();
748 }
749 return true;
750}
751
752/**
753 * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`.
754 *
755 * \param[out] l The destination `IOMX::ComponentInfo`.
756 * \param[in] t The source `IOmx::ComponentInfo`.
757 */
758// convert: IOmx::ComponentInfo -> IOMX::ComponentInfo
759inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) {
760 l->mName = t.mName.c_str();
761 l->mRoles.clear();
762 for (size_t i = 0; i < t.mRoles.size(); ++i) {
763 l->mRoles.push_back(String8(t.mRoles[i].c_str()));
764 }
765 return true;
766}
767
768/**
769 * \brief Convert `OMX_BOOL` to `bool`.
770 *
771 * \param[in] l The source `OMX_BOOL`.
772 * \return The destination `bool`.
773 */
774// convert: OMX_BOOL -> bool
775inline bool toRawBool(OMX_BOOL l) {
776 return l == OMX_FALSE ? false : true;
777}
778
779/**
780 * \brief Convert `bool` to `OMX_BOOL`.
781 *
782 * \param[in] t The source `bool`.
783 * \return The destination `OMX_BOOL`.
784 */
785// convert: bool -> OMX_BOOL
786inline OMX_BOOL toEnumBool(bool t) {
787 return t ? OMX_TRUE : OMX_FALSE;
788}
789
790/**
791 * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`.
792 *
793 * \param[in] l The source `OMX_COMMANDTYPE`.
794 * \return The underlying value of type `uint32_t`.
795 *
796 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
797 */
798// convert: OMX_COMMANDTYPE -> uint32_t
799inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
800 return static_cast<uint32_t>(l);
801}
802
803/**
804 * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`.
805 *
806 * \param[in] t The source `uint32_t`.
807 * \return The corresponding enum value of type `OMX_COMMANDTYPE`.
808 *
809 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
810 */
811// convert: uint32_t -> OMX_COMMANDTYPE
812inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) {
813 return static_cast<OMX_COMMANDTYPE>(t);
814}
815
816/**
817 * \brief Convert `OMX_INDEXTYPE` to `uint32_t`.
818 *
819 * \param[in] l The source `OMX_INDEXTYPE`.
820 * \return The underlying value of type `uint32_t`.
821 *
822 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
823 */
824// convert: OMX_INDEXTYPE -> uint32_t
825inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
826 return static_cast<uint32_t>(l);
827}
828
829/**
830 * \brief Convert `uint32_t` to `OMX_INDEXTYPE`.
831 *
832 * \param[in] t The source `uint32_t`.
833 * \return The corresponding enum value of type `OMX_INDEXTYPE`.
834 *
835 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
836 */
837// convert: uint32_t -> OMX_INDEXTYPE
838inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) {
839 return static_cast<OMX_INDEXTYPE>(t);
840}
841
842/**
843 * \brief Convert `IOMX::PortMode` to `PortMode`.
844 *
845 * \param[in] l The source `IOMX::PortMode`.
846 * \return The destination `PortMode`.
847 */
848// convert: IOMX::PortMode -> PortMode
849inline PortMode toHardwarePortMode(IOMX::PortMode l) {
850 return static_cast<PortMode>(l);
851}
852
853/**
854 * \brief Convert `PortMode` to `IOMX::PortMode`.
855 *
856 * \param[in] t The source `PortMode`.
857 * \return The destination `IOMX::PortMode`.
858 */
859// convert: PortMode -> IOMX::PortMode
860inline IOMX::PortMode toIOMXPortMode(PortMode t) {
861 return static_cast<IOMX::PortMode>(t);
862}
863
864/**
865 * \brief Convert `OMX_TICKS` to `uint64_t`.
866 *
867 * \param[in] l The source `OMX_TICKS`.
868 * \return The destination `uint64_t`.
869 */
870// convert: OMX_TICKS -> uint64_t
871inline uint64_t toRawTicks(OMX_TICKS l) {
872#ifndef OMX_SKIP64BIT
873 return static_cast<uint64_t>(l);
874#else
875 return static_cast<uint64_t>(l.nLowPart) |
876 static_cast<uint64_t>(l.nHighPart << 32);
877#endif
878}
879
880/**
881 * \brief Convert `uint64_t` to `OMX_TICKS`.
882 *
883 * \param[in] l The source `uint64_t`.
884 * \return The destination `OMX_TICKS`.
885 */
886// convert: uint64_t -> OMX_TICKS
887inline OMX_TICKS toOMXTicks(uint64_t t) {
888#ifndef OMX_SKIP64BIT
889 return static_cast<OMX_TICKS>(t);
890#else
891 return OMX_TICKS{
892 static_cast<uint32_t>(t & 0xFFFFFFFF),
893 static_cast<uint32_t>(t >> 32)};
894#endif
895}
896
897/**
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -0800898 * Conversion functions for types outside media
899 * ============================================
900 *
901 * Some objects in libui and libgui that were made to go through binder calls do
902 * not expose ways to read or write their fields to the public. To pass an
903 * object of this kind through the HIDL boundary, translation functions need to
904 * work around the access restriction by using the publicly available
905 * `flatten()` and `unflatten()` functions.
906 *
907 * All `flatten()` and `unflatten()` overloads follow the same convention as
908 * follows:
909 *
910 * status_t flatten(ObjectType const& object,
911 * [OtherType const& other, ...]
912 * void*& buffer, size_t& size,
913 * int*& fds, size_t& numFds)
914 *
915 * status_t unflatten(ObjectType* object,
916 * [OtherType* other, ...,]
917 * void*& buffer, size_t& size,
918 * int*& fds, size_t& numFds)
919 *
920 * The number of `other` parameters varies depending on the `ObjectType`. For
921 * example, in the process of unflattening an object that contains
922 * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
923 * be created.
924 *
925 * The last four parameters always work the same way in all overloads of
926 * `flatten()` and `unflatten()`:
927 * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
928 * `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
929 * `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
930 * size (in ints) of the fd buffer pointed to by `fds`.
931 * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
932 * from, `size` is the size (in bytes) of the non-fd buffer pointed to by
933 * `buffer`, `fds` is the pointer to the fd buffer to be read from, and
934 * `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
935 * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
936 * will be advanced, while `size` and `numFds` will be decreased to reflect
937 * how much storage/data of the two buffers (fd and non-fd) have been used.
938 * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
939 * `numFds` are invalid.
940 *
941 * The return value of a successful `flatten()` or `unflatten()` call will be
942 * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
943 *
944 * For each object type that supports flattening, there will be two accompanying
945 * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
946 * return the size of the non-fd buffer that the object will need for
947 * flattening. `getFdCount()` will return the size of the fd buffer that the
948 * object will need for flattening.
949 *
950 * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
951 * `flatten()` and `unflatten()`, are similar to functions of the same name in
952 * the abstract class `Flattenable`. The only difference is that functions in
953 * this file are not member functions of the object type. For example, we write
954 *
955 * flatten(x, buffer, size, fds, numFds)
956 *
957 * instead of
958 *
959 * x.flatten(buffer, size, fds, numFds)
960 *
961 * because we cannot modify the type of `x`.
962 *
963 * There is one exception to the naming convention: `hidl_handle` that
964 * represents a fence. The four functions for this "Fence" type have the word
965 * "Fence" attched to their names because the object type, which is
966 * `hidl_handle`, does not carry the special meaning that the object itself can
967 * only contain zero or one file descriptor.
968 */
969
970// Ref: frameworks/native/libs/ui/Fence.cpp
971
972/**
973 * \brief Return the size of the non-fd buffer required to flatten a fence.
974 *
975 * \param[in] fence The input fence of type `hidl_handle`.
976 * \return The required size of the flat buffer.
977 *
978 * The current version of this function always returns 4, which is the number of
979 * bytes required to store the number of file descriptors contained in the fd
980 * part of the flat buffer.
981 */
982inline size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
983 return 4;
984};
985
986/**
987 * \brief Return the number of file descriptors contained in a fence.
988 *
989 * \param[in] fence The input fence of type `hidl_handle`.
990 * \return `0` if \p fence does not contain a valid file descriptor, or `1`
991 * otherwise.
992 */
993inline size_t getFenceFdCount(hidl_handle const& fence) {
994 return native_handle_read_fd(fence) == -1 ? 0 : 1;
995}
996
997/**
998 * \brief Unflatten `Fence` to `hidl_handle`.
999 *
1000 * \param[out] fence The destination `hidl_handle`.
1001 * \param[out] nh The underlying native handle.
1002 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1003 * \param[in,out] size The size of the flat non-fd buffer.
1004 * \param[in,out] fds The pointer to the flat fd buffer.
1005 * \param[in,out] numFds The size of the flat fd buffer.
1006 * \return `NO_ERROR` on success; other value on failure.
1007 *
1008 * If the return value is `NO_ERROR`, \p nh will point to a newly created
1009 * native handle, which needs to be deleted with `native_handle_delete()`
1010 * afterwards.
1011 */
1012inline status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
1013 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1014 if (size < 4) {
1015 return NO_MEMORY;
1016 }
1017
1018 uint32_t numFdsInHandle;
1019 FlattenableUtils::read(buffer, size, numFdsInHandle);
1020
1021 if (numFdsInHandle > 1) {
1022 return BAD_VALUE;
1023 }
1024
1025 if (numFds < numFdsInHandle) {
1026 return NO_MEMORY;
1027 }
1028
1029 if (numFdsInHandle) {
1030 *nh = native_handle_create_from_fd(*fds);
1031 if (*nh == nullptr) {
1032 return NO_MEMORY;
1033 }
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08001034 *fence = *nh;
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001035 ++fds;
1036 --numFds;
1037 } else {
1038 *nh = nullptr;
1039 *fence = hidl_handle();
1040 }
1041
1042 return NO_ERROR;
1043}
1044
1045/**
1046 * \brief Flatten `hidl_handle` as `Fence`.
1047 *
1048 * \param[in] t The source `hidl_handle`.
1049 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1050 * \param[in,out] size The size of the flat non-fd buffer.
1051 * \param[in,out] fds The pointer to the flat fd buffer.
1052 * \param[in,out] numFds The size of the flat fd buffer.
1053 * \return `NO_ERROR` on success; other value on failure.
1054 */
1055inline status_t flattenFence(hidl_handle const& fence,
1056 void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1057 if (size < getFenceFlattenedSize(fence) ||
1058 numFds < getFenceFdCount(fence)) {
1059 return NO_MEMORY;
1060 }
1061 // Cast to uint32_t since the size of a size_t can vary between 32- and
1062 // 64-bit processes
1063 FlattenableUtils::write(buffer, size,
1064 static_cast<uint32_t>(getFenceFdCount(fence)));
1065 int fd = native_handle_read_fd(fence);
1066 if (fd != -1) {
1067 *fds = fd;
1068 ++fds;
1069 --numFds;
1070 }
1071 return NO_ERROR;
1072}
1073
1074/**
1075 * \brief Wrap `Fence` in `hidl_handle`.
1076 *
1077 * \param[out] t The wrapper of type `hidl_handle`.
1078 * \param[out] nh The native handle pointed to by \p t.
1079 * \param[in] l The source `Fence`.
1080 *
1081 * On success, \p nh will hold a newly created native handle, which must be
1082 * deleted manually with `native_handle_delete()` afterwards.
1083 */
1084// wrap: Fence -> hidl_handle
1085inline bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
1086 size_t const baseSize = l.getFlattenedSize();
1087 std::unique_ptr<uint8_t[]> baseBuffer(
1088 new (std::nothrow) uint8_t[baseSize]);
1089 if (!baseBuffer) {
1090 return false;
1091 }
1092
1093 size_t const baseNumFds = l.getFdCount();
1094 std::unique_ptr<int[]> baseFds(
1095 new (std::nothrow) int[baseNumFds]);
1096 if (!baseFds) {
1097 return false;
1098 }
1099
1100 void* buffer = static_cast<void*>(baseBuffer.get());
1101 size_t size = baseSize;
1102 int* fds = static_cast<int*>(baseFds.get());
1103 size_t numFds = baseNumFds;
1104 if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
1105 return false;
1106 }
1107
1108 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1109 size = baseSize;
1110 int const* constFds = static_cast<int const*>(baseFds.get());
1111 numFds = baseNumFds;
1112 if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
1113 != NO_ERROR) {
1114 return false;
1115 }
1116
1117 return true;
1118}
1119
1120/**
1121 * \brief Convert `hidl_handle` to `Fence`.
1122 *
1123 * \param[out] l The destination `Fence`. `l` must not have been used
1124 * (`l->isValid()` must return `false`) before this function is called.
1125 * \param[in] t The source `hidl_handle`.
1126 *
1127 * If \p t contains a valid file descriptor, it will be duplicated.
1128 */
1129// convert: hidl_handle -> Fence
1130inline bool convertTo(Fence* l, hidl_handle const& t) {
1131 int fd = native_handle_read_fd(t);
1132 if (fd != -1) {
1133 fd = dup(fd);
1134 if (fd == -1) {
1135 return false;
1136 }
1137 }
1138 native_handle_t* nh = native_handle_create_from_fd(fd);
1139 if (nh == nullptr) {
1140 if (fd != -1) {
1141 close(fd);
1142 }
1143 return false;
1144 }
1145
1146 size_t const baseSize = getFenceFlattenedSize(t);
1147 std::unique_ptr<uint8_t[]> baseBuffer(
1148 new (std::nothrow) uint8_t[baseSize]);
1149 if (!baseBuffer) {
1150 native_handle_delete(nh);
1151 return false;
1152 }
1153
1154 size_t const baseNumFds = getFenceFdCount(t);
1155 std::unique_ptr<int[]> baseFds(
1156 new (std::nothrow) int[baseNumFds]);
1157 if (!baseFds) {
1158 native_handle_delete(nh);
1159 return false;
1160 }
1161
1162 void* buffer = static_cast<void*>(baseBuffer.get());
1163 size_t size = baseSize;
1164 int* fds = static_cast<int*>(baseFds.get());
1165 size_t numFds = baseNumFds;
1166 if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
1167 native_handle_delete(nh);
1168 return false;
1169 }
1170 native_handle_delete(nh);
1171
1172 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1173 size = baseSize;
1174 int const* constFds = static_cast<int const*>(baseFds.get());
1175 numFds = baseNumFds;
1176 if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
1177 return false;
1178 }
1179
1180 return true;
1181}
1182
1183// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
1184
1185/**
1186 * \brief Return the size of the non-fd buffer required to flatten
1187 * `FenceTimeSnapshot`.
1188 *
1189 * \param[in] t The input `FenceTimeSnapshot`.
1190 * \return The required size of the flat buffer.
1191 */
1192inline size_t getFlattenedSize(
1193 IOmxBufferProducer::FenceTimeSnapshot const& t) {
1194 constexpr size_t min = sizeof(t.state);
1195 switch (t.state) {
1196 case IOmxBufferProducer::FenceTimeSnapshot::State::EMPTY:
1197 return min;
1198 case IOmxBufferProducer::FenceTimeSnapshot::State::FENCE:
1199 return min + getFenceFlattenedSize(t.fence);
1200 case IOmxBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
1201 return min + sizeof(
1202 ::android::FenceTime::Snapshot::signalTime);
1203 }
1204 return 0;
1205}
1206
1207/**
1208 * \brief Return the number of file descriptors contained in
1209 * `FenceTimeSnapshot`.
1210 *
1211 * \param[in] t The input `FenceTimeSnapshot`.
1212 * \return The number of file descriptors contained in \p snapshot.
1213 */
1214inline size_t getFdCount(
1215 IOmxBufferProducer::FenceTimeSnapshot const& t) {
1216 return t.state ==
1217 IOmxBufferProducer::FenceTimeSnapshot::State::FENCE ?
1218 getFenceFdCount(t.fence) : 0;
1219}
1220
1221/**
1222 * \brief Flatten `FenceTimeSnapshot`.
1223 *
1224 * \param[in] t The source `FenceTimeSnapshot`.
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` if `t.state ==
1232 * FENCE`.
1233 */
1234inline status_t flatten(IOmxBufferProducer::FenceTimeSnapshot const& t,
1235 void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1236 if (size < getFlattenedSize(t)) {
1237 return NO_MEMORY;
1238 }
1239
1240 switch (t.state) {
1241 case IOmxBufferProducer::FenceTimeSnapshot::State::EMPTY:
1242 FlattenableUtils::write(buffer, size,
1243 ::android::FenceTime::Snapshot::State::EMPTY);
1244 return NO_ERROR;
1245 case IOmxBufferProducer::FenceTimeSnapshot::State::FENCE:
1246 FlattenableUtils::write(buffer, size,
1247 ::android::FenceTime::Snapshot::State::FENCE);
1248 return flattenFence(t.fence, buffer, size, fds, numFds);
1249 case IOmxBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
1250 FlattenableUtils::write(buffer, size,
1251 ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
1252 FlattenableUtils::write(buffer, size, t.signalTimeNs);
1253 return NO_ERROR;
1254 }
1255 return NO_ERROR;
1256}
1257
1258/**
1259 * \brief Unflatten `FenceTimeSnapshot`.
1260 *
1261 * \param[out] t The destination `FenceTimeSnapshot`.
1262 * \param[out] nh The underlying native handle.
1263 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1264 * \param[in,out] size The size of the flat non-fd buffer.
1265 * \param[in,out] fds The pointer to the flat fd buffer.
1266 * \param[in,out] numFds The size of the flat fd buffer.
1267 * \return `NO_ERROR` on success; other value on failure.
1268 *
1269 * If the return value is `NO_ERROR` and the constructed snapshot contains a
1270 * file descriptor, \p nh will be created to hold that file descriptor. In this
1271 * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
1272 */
1273inline status_t unflatten(
1274 IOmxBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
1275 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1276 if (size < sizeof(t->state)) {
1277 return NO_MEMORY;
1278 }
1279
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08001280 *nh = nullptr;
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001281 ::android::FenceTime::Snapshot::State state;
1282 FlattenableUtils::read(buffer, size, state);
1283 switch (state) {
1284 case ::android::FenceTime::Snapshot::State::EMPTY:
1285 t->state = IOmxBufferProducer::FenceTimeSnapshot::State::EMPTY;
1286 return NO_ERROR;
1287 case ::android::FenceTime::Snapshot::State::FENCE:
1288 t->state = IOmxBufferProducer::FenceTimeSnapshot::State::FENCE;
1289 return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
1290 case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
1291 t->state = IOmxBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
1292 if (size < sizeof(t->signalTimeNs)) {
1293 return NO_MEMORY;
1294 }
1295 FlattenableUtils::read(buffer, size, t->signalTimeNs);
1296 return NO_ERROR;
1297 }
1298 return NO_ERROR;
1299}
1300
1301// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
1302
1303/**
1304 * \brief Return a lower bound on the size of the non-fd buffer required to
1305 * flatten `FrameEventsDelta`.
1306 *
1307 * \param[in] t The input `FrameEventsDelta`.
1308 * \return A lower bound on the size of the flat buffer.
1309 */
1310constexpr size_t minFlattenedSize(
1311 IOmxBufferProducer::FrameEventsDelta const& /* t */) {
1312 return sizeof(uint64_t) + // mFrameNumber
1313 sizeof(uint8_t) + // mIndex
1314 sizeof(uint8_t) + // mAddPostCompositeCalled
1315 sizeof(uint8_t) + // mAddRetireCalled
1316 sizeof(uint8_t) + // mAddReleaseCalled
1317 sizeof(nsecs_t) + // mPostedTime
1318 sizeof(nsecs_t) + // mRequestedPresentTime
1319 sizeof(nsecs_t) + // mLatchTime
1320 sizeof(nsecs_t) + // mFirstRefreshStartTime
1321 sizeof(nsecs_t); // mLastRefreshStartTime
1322}
1323
1324/**
1325 * \brief Return the size of the non-fd buffer required to flatten
1326 * `FrameEventsDelta`.
1327 *
1328 * \param[in] t The input `FrameEventsDelta`.
1329 * \return The required size of the flat buffer.
1330 */
1331inline size_t getFlattenedSize(
1332 IOmxBufferProducer::FrameEventsDelta const& t) {
1333 return minFlattenedSize(t) +
1334 getFlattenedSize(t.gpuCompositionDoneFence) +
1335 getFlattenedSize(t.displayPresentFence) +
1336 getFlattenedSize(t.displayRetireFence) +
1337 getFlattenedSize(t.releaseFence);
1338};
1339
1340/**
1341 * \brief Return the number of file descriptors contained in
1342 * `FrameEventsDelta`.
1343 *
1344 * \param[in] t The input `FrameEventsDelta`.
1345 * \return The number of file descriptors contained in \p t.
1346 */
1347inline size_t getFdCount(
1348 IOmxBufferProducer::FrameEventsDelta const& t) {
1349 return getFdCount(t.gpuCompositionDoneFence) +
1350 getFdCount(t.displayPresentFence) +
1351 getFdCount(t.displayRetireFence) +
1352 getFdCount(t.releaseFence);
1353};
1354
1355/**
1356 * \brief Unflatten `FrameEventsDelta`.
1357 *
1358 * \param[out] t The destination `FrameEventsDelta`.
1359 * \param[out] nh The underlying array of native handles.
1360 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1361 * \param[in,out] size The size of the flat non-fd buffer.
1362 * \param[in,out] fds The pointer to the flat fd buffer.
1363 * \param[in,out] numFds The size of the flat fd buffer.
1364 * \return `NO_ERROR` on success; other value on failure.
1365 *
1366 * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
1367 * populated with `nullptr` or newly created handles. Each non-null slot in \p
1368 * nh will need to be deleted manually with `native_handle_delete()`.
1369 */
1370inline status_t unflatten(IOmxBufferProducer::FrameEventsDelta* t,
1371 std::vector<native_handle_t*>* nh,
1372 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1373 if (size < minFlattenedSize(*t)) {
1374 return NO_MEMORY;
1375 }
1376 FlattenableUtils::read(buffer, size, t->frameNumber);
1377
1378 // These were written as uint8_t for alignment.
1379 uint8_t temp = 0;
1380 FlattenableUtils::read(buffer, size, temp);
1381 size_t index = static_cast<size_t>(temp);
1382 if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
1383 return BAD_VALUE;
1384 }
1385 t->index = static_cast<uint32_t>(index);
1386
1387 FlattenableUtils::read(buffer, size, temp);
1388 t->addPostCompositeCalled = static_cast<bool>(temp);
1389 FlattenableUtils::read(buffer, size, temp);
1390 t->addRetireCalled = static_cast<bool>(temp);
1391 FlattenableUtils::read(buffer, size, temp);
1392 t->addReleaseCalled = static_cast<bool>(temp);
1393
1394 FlattenableUtils::read(buffer, size, t->postedTimeNs);
1395 FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
1396 FlattenableUtils::read(buffer, size, t->latchTimeNs);
1397 FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
1398 FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
1399 FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
1400
1401 // Fences
1402 IOmxBufferProducer::FenceTimeSnapshot* tSnapshot[4];
1403 tSnapshot[0] = &t->gpuCompositionDoneFence;
1404 tSnapshot[1] = &t->displayPresentFence;
1405 tSnapshot[2] = &t->displayRetireFence;
1406 tSnapshot[3] = &t->releaseFence;
1407 nh->resize(4);
1408 for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
1409 status_t status = unflatten(
1410 tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
1411 buffer, size, fds, numFds);
1412 if (status != NO_ERROR) {
1413 while (snapshotIndex > 0) {
1414 --snapshotIndex;
1415 if ((*nh)[snapshotIndex] != nullptr) {
1416 native_handle_delete((*nh)[snapshotIndex]);
1417 }
1418 }
1419 return status;
1420 }
1421 }
1422 return NO_ERROR;
1423}
1424
1425/**
1426 * \brief Flatten `FrameEventsDelta`.
1427 *
1428 * \param[in] t The source `FrameEventsDelta`.
1429 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1430 * \param[in,out] size The size of the flat non-fd buffer.
1431 * \param[in,out] fds The pointer to the flat fd buffer.
1432 * \param[in,out] numFds The size of the flat fd buffer.
1433 * \return `NO_ERROR` on success; other value on failure.
1434 *
1435 * This function will duplicate file descriptors contained in \p t.
1436 */
1437// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
1438// FrameEventsDelta::flatten
1439inline status_t flatten(IOmxBufferProducer::FrameEventsDelta const& t,
1440 void*& buffer, size_t& size, int*& fds, size_t numFds) {
1441 // Check that t.index is within a valid range.
1442 if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
1443 || t.index > std::numeric_limits<uint8_t>::max()) {
1444 return BAD_VALUE;
1445 }
1446
1447 FlattenableUtils::write(buffer, size, t.frameNumber);
1448
1449 // These are static_cast to uint8_t for alignment.
1450 FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
1451 FlattenableUtils::write(
1452 buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
1453 FlattenableUtils::write(
1454 buffer, size, static_cast<uint8_t>(t.addRetireCalled));
1455 FlattenableUtils::write(
1456 buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
1457
1458 FlattenableUtils::write(buffer, size, t.postedTimeNs);
1459 FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
1460 FlattenableUtils::write(buffer, size, t.latchTimeNs);
1461 FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
1462 FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
1463 FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
1464
1465 // Fences
1466 IOmxBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
1467 tSnapshot[0] = &t.gpuCompositionDoneFence;
1468 tSnapshot[1] = &t.displayPresentFence;
1469 tSnapshot[2] = &t.displayRetireFence;
1470 tSnapshot[3] = &t.releaseFence;
1471 for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
1472 status_t status = flatten(
1473 *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
1474 if (status != NO_ERROR) {
1475 return status;
1476 }
1477 }
1478 return NO_ERROR;
1479}
1480
1481// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
1482
1483/**
1484 * \brief Return the size of the non-fd buffer required to flatten
1485 * `IOmxBufferProducer::FrameEventHistoryDelta`.
1486 *
1487 * \param[in] t The input `IOmxBufferProducer::FrameEventHistoryDelta`.
1488 * \return The required size of the flat buffer.
1489 */
1490inline size_t getFlattenedSize(
1491 IOmxBufferProducer::FrameEventHistoryDelta const& t) {
Brian Anderson1f82e092017-02-13 15:23:13 -08001492 size_t size = 4 + // mDeltas.size()
1493 sizeof(t.compositorTiming);
1494 for (size_t i = 0; i < t.deltas.size(); ++i) {
1495 size += getFlattenedSize(t.deltas[i]);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001496 }
1497 return size;
1498}
1499
1500/**
1501 * \brief Return the number of file descriptors contained in
1502 * `IOmxBufferProducer::FrameEventHistoryDelta`.
1503 *
1504 * \param[in] t The input `IOmxBufferProducer::FrameEventHistoryDelta`.
1505 * \return The number of file descriptors contained in \p t.
1506 */
1507inline size_t getFdCount(
1508 IOmxBufferProducer::FrameEventHistoryDelta const& t) {
1509 size_t numFds = 0;
Brian Anderson1f82e092017-02-13 15:23:13 -08001510 for (size_t i = 0; i < t.deltas.size(); ++i) {
1511 numFds += getFdCount(t.deltas[i]);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001512 }
1513 return numFds;
1514}
1515
1516/**
1517 * \brief Unflatten `FrameEventHistoryDelta`.
1518 *
1519 * \param[out] t The destination `FrameEventHistoryDelta`.
1520 * \param[out] nh The underlying array of arrays of native handles.
1521 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1522 * \param[in,out] size The size of the flat non-fd buffer.
1523 * \param[in,out] fds The pointer to the flat fd buffer.
1524 * \param[in,out] numFds The size of the flat fd buffer.
1525 * \return `NO_ERROR` on success; other value on failure.
1526 *
1527 * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
1528 * newly created handles. The second dimension of \p nh will be 4. Each non-null
1529 * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
1530 */
1531inline status_t unflatten(
1532 IOmxBufferProducer::FrameEventHistoryDelta* t,
1533 std::vector<std::vector<native_handle_t*> >* nh,
1534 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1535 if (size < 4) {
1536 return NO_MEMORY;
1537 }
1538
Brian Anderson1f82e092017-02-13 15:23:13 -08001539 FlattenableUtils::read(buffer, size, t->compositorTiming);
1540
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001541 uint32_t deltaCount = 0;
1542 FlattenableUtils::read(buffer, size, deltaCount);
1543 if (static_cast<size_t>(deltaCount) >
1544 ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
1545 return BAD_VALUE;
1546 }
Brian Anderson1f82e092017-02-13 15:23:13 -08001547 t->deltas.resize(deltaCount);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001548 nh->resize(deltaCount);
1549 for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
1550 status_t status = unflatten(
Brian Anderson1f82e092017-02-13 15:23:13 -08001551 &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001552 buffer, size, fds, numFds);
1553 if (status != NO_ERROR) {
1554 return status;
1555 }
1556 }
1557 return NO_ERROR;
1558}
1559
1560/**
1561 * \brief Flatten `FrameEventHistoryDelta`.
1562 *
1563 * \param[in] t The source `FrameEventHistoryDelta`.
1564 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1565 * \param[in,out] size The size of the flat non-fd buffer.
1566 * \param[in,out] fds The pointer to the flat fd buffer.
1567 * \param[in,out] numFds The size of the flat fd buffer.
1568 * \return `NO_ERROR` on success; other value on failure.
1569 *
1570 * This function will duplicate file descriptors contained in \p t.
1571 */
1572inline status_t flatten(
1573 IOmxBufferProducer::FrameEventHistoryDelta const& t,
1574 void*& buffer, size_t& size, int*& fds, size_t& numFds) {
Brian Anderson1f82e092017-02-13 15:23:13 -08001575 if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001576 return BAD_VALUE;
1577 }
1578 if (size < getFlattenedSize(t)) {
1579 return NO_MEMORY;
1580 }
1581
Brian Anderson1f82e092017-02-13 15:23:13 -08001582 FlattenableUtils::write(buffer, size, t.compositorTiming);
1583
1584 FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
1585 for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
1586 status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001587 if (status != NO_ERROR) {
1588 return status;
1589 }
1590 }
1591 return NO_ERROR;
1592}
1593
1594/**
1595 * \brief Wrap `::android::FrameEventHistoryData` in
1596 * `IOmxBufferProducer::FrameEventHistoryDelta`.
1597 *
1598 * \param[out] t The wrapper of type
1599 * `IOmxBufferProducer::FrameEventHistoryDelta`.
1600 * \param[out] nh The array of array of native handles that are referred to by
1601 * members of \p t.
1602 * \param[in] l The source `::android::FrameEventHistoryDelta`.
1603 *
1604 * On success, each member of \p nh will be either `nullptr` or a newly created
1605 * native handle. All the non-`nullptr` elements must be deleted individually
1606 * with `native_handle_delete()`.
1607 */
1608inline bool wrapAs(IOmxBufferProducer::FrameEventHistoryDelta* t,
1609 std::vector<std::vector<native_handle_t*> >* nh,
1610 ::android::FrameEventHistoryDelta const& l) {
1611
1612 size_t const baseSize = l.getFlattenedSize();
1613 std::unique_ptr<uint8_t[]> baseBuffer(
1614 new (std::nothrow) uint8_t[baseSize]);
1615 if (!baseBuffer) {
1616 return false;
1617 }
1618
1619 size_t const baseNumFds = l.getFdCount();
1620 std::unique_ptr<int[]> baseFds(
1621 new (std::nothrow) int[baseNumFds]);
1622 if (!baseFds) {
1623 return false;
1624 }
1625
1626 void* buffer = static_cast<void*>(baseBuffer.get());
1627 size_t size = baseSize;
1628 int* fds = baseFds.get();
1629 size_t numFds = baseNumFds;
1630 if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
1631 return false;
1632 }
1633
1634 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1635 size = baseSize;
1636 int const* constFds = static_cast<int const*>(baseFds.get());
1637 numFds = baseNumFds;
1638 if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
1639 return false;
1640 }
1641
1642 return true;
1643}
1644
1645/**
1646 * \brief Convert `IOmxBufferProducer::FrameEventHistoryDelta` to
1647 * `::android::FrameEventHistoryDelta`.
1648 *
1649 * \param[out] l The destination `::android::FrameEventHistoryDelta`.
1650 * \param[in] t The source `IOmxBufferProducer::FrameEventHistoryDelta`.
1651 *
1652 * This function will duplicate all file descriptors contained in \p t.
1653 */
1654inline bool convertTo(
1655 ::android::FrameEventHistoryDelta* l,
1656 IOmxBufferProducer::FrameEventHistoryDelta const& t) {
1657
1658 size_t const baseSize = getFlattenedSize(t);
1659 std::unique_ptr<uint8_t[]> baseBuffer(
1660 new (std::nothrow) uint8_t[baseSize]);
1661 if (!baseBuffer) {
1662 return false;
1663 }
1664
1665 size_t const baseNumFds = getFdCount(t);
1666 std::unique_ptr<int[]> baseFds(
1667 new (std::nothrow) int[baseNumFds]);
1668 if (!baseFds) {
1669 return false;
1670 }
1671
1672 void* buffer = static_cast<void*>(baseBuffer.get());
1673 size_t size = baseSize;
1674 int* fds = static_cast<int*>(baseFds.get());
1675 size_t numFds = baseNumFds;
1676 if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
1677 return false;
1678 }
1679
1680 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1681 size = baseSize;
1682 int const* constFds = static_cast<int const*>(baseFds.get());
1683 numFds = baseNumFds;
1684 if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
1685 return false;
1686 }
1687
1688 return true;
1689}
1690
1691// Ref: frameworks/native/libs/ui/Region.cpp
1692
1693/**
1694 * \brief Return the size of the buffer required to flatten `Region`.
1695 *
1696 * \param[in] t The input `Region`.
1697 * \return The required size of the flat buffer.
1698 */
1699inline size_t getFlattenedSize(Region const& t) {
1700 return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
1701}
1702
1703/**
1704 * \brief Unflatten `Region`.
1705 *
1706 * \param[out] t The destination `Region`.
1707 * \param[in,out] buffer The pointer to the flat buffer.
1708 * \param[in,out] size The size of the flat buffer.
1709 * \return `NO_ERROR` on success; other value on failure.
1710 */
1711inline status_t unflatten(Region* t, void const*& buffer, size_t& size) {
1712 if (size < sizeof(uint32_t)) {
1713 return NO_MEMORY;
1714 }
1715
1716 uint32_t numRects = 0;
1717 FlattenableUtils::read(buffer, size, numRects);
1718 if (size < numRects * sizeof(Rect)) {
1719 return NO_MEMORY;
1720 }
1721 if (numRects > (UINT32_MAX / sizeof(Rect))) {
1722 return NO_MEMORY;
1723 }
1724
1725 t->resize(numRects);
1726 for (size_t r = 0; r < numRects; ++r) {
1727 ::android::Rect rect(::android::Rect::EMPTY_RECT);
1728 status_t status = rect.unflatten(buffer, size);
1729 if (status != NO_ERROR) {
1730 return status;
1731 }
1732 FlattenableUtils::advance(buffer, size, sizeof(rect));
1733 (*t)[r] = Rect{
1734 static_cast<int32_t>(rect.left),
1735 static_cast<int32_t>(rect.top),
1736 static_cast<int32_t>(rect.right),
1737 static_cast<int32_t>(rect.bottom)};
1738 }
1739 return NO_ERROR;
1740}
1741
1742/**
1743 * \brief Flatten `Region`.
1744 *
1745 * \param[in] t The source `Region`.
1746 * \param[in,out] buffer The pointer to the flat buffer.
1747 * \param[in,out] size The size of the flat buffer.
1748 * \return `NO_ERROR` on success; other value on failure.
1749 */
1750inline status_t flatten(Region const& t, void*& buffer, size_t& size) {
1751 if (size < getFlattenedSize(t)) {
1752 return NO_MEMORY;
1753 }
1754
1755 FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
1756 for (size_t r = 0; r < t.size(); ++r) {
1757 ::android::Rect rect(
1758 static_cast<int32_t>(t[r].left),
1759 static_cast<int32_t>(t[r].top),
1760 static_cast<int32_t>(t[r].right),
1761 static_cast<int32_t>(t[r].bottom));
1762 status_t status = rect.flatten(buffer, size);
1763 if (status != NO_ERROR) {
1764 return status;
1765 }
1766 FlattenableUtils::advance(buffer, size, sizeof(rect));
1767 }
1768 return NO_ERROR;
1769}
1770
1771/**
1772 * \brief Convert `::android::Region` to `Region`.
1773 *
1774 * \param[out] t The destination `Region`.
1775 * \param[in] l The source `::android::Region`.
1776 */
1777// convert: ::android::Region -> Region
1778inline bool convertTo(Region* t, ::android::Region const& l) {
1779 size_t const baseSize = l.getFlattenedSize();
1780 std::unique_ptr<uint8_t[]> baseBuffer(
1781 new (std::nothrow) uint8_t[baseSize]);
1782 if (!baseBuffer) {
1783 return false;
1784 }
1785
1786 void* buffer = static_cast<void*>(baseBuffer.get());
1787 size_t size = baseSize;
1788 if (l.flatten(buffer, size) != NO_ERROR) {
1789 return false;
1790 }
1791
1792 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1793 size = baseSize;
1794 if (unflatten(t, constBuffer, size) != NO_ERROR) {
1795 return false;
1796 }
1797
1798 return true;
1799}
1800
1801/**
1802 * \brief Convert `Region` to `::android::Region`.
1803 *
1804 * \param[out] l The destination `::android::Region`.
1805 * \param[in] t The source `Region`.
1806 */
1807// convert: Region -> ::android::Region
1808inline bool convertTo(::android::Region* l, Region const& t) {
1809 size_t const baseSize = getFlattenedSize(t);
1810 std::unique_ptr<uint8_t[]> baseBuffer(
1811 new (std::nothrow) uint8_t[baseSize]);
1812 if (!baseBuffer) {
1813 return false;
1814 }
1815
1816 void* buffer = static_cast<void*>(baseBuffer.get());
1817 size_t size = baseSize;
1818 if (flatten(t, buffer, size) != NO_ERROR) {
1819 return false;
1820 }
1821
1822 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
1823 size = baseSize;
1824 if (l->unflatten(constBuffer, size) != NO_ERROR) {
1825 return false;
1826 }
1827
1828 return true;
1829}
1830
1831// Ref: frameworks/native/libs/gui/IGraphicBufferProducer.cpp:
1832// IGraphicBufferProducer::QueueBufferInput
1833
1834/**
1835 * \brief Return a lower bound on the size of the buffer required to flatten
1836 * `IOmxBufferProducer::QueueBufferInput`.
1837 *
1838 * \param[in] t The input `IOmxBufferProducer::QueueBufferInput`.
1839 * \return A lower bound on the size of the flat buffer.
1840 */
1841constexpr size_t minFlattenedSize(
1842 IOmxBufferProducer::QueueBufferInput const& /* t */) {
1843 return sizeof(int64_t) + // timestamp
1844 sizeof(int) + // isAutoTimestamp
1845 sizeof(android_dataspace) + // dataSpace
1846 sizeof(::android::Rect) + // crop
1847 sizeof(int) + // scalingMode
1848 sizeof(uint32_t) + // transform
1849 sizeof(uint32_t) + // stickyTransform
1850 sizeof(bool); // getFrameTimestamps
1851}
1852
1853/**
1854 * \brief Return the size of the buffer required to flatten
1855 * `IOmxBufferProducer::QueueBufferInput`.
1856 *
1857 * \param[in] t The input `IOmxBufferProducer::QueueBufferInput`.
1858 * \return The required size of the flat buffer.
1859 */
1860inline size_t getFlattenedSize(IOmxBufferProducer::QueueBufferInput const& t) {
1861 return minFlattenedSize(t) +
1862 getFenceFlattenedSize(t.fence) +
1863 getFlattenedSize(t.surfaceDamage);
1864}
1865
1866/**
1867 * \brief Return the number of file descriptors contained in
1868 * `IOmxBufferProducer::QueueBufferInput`.
1869 *
1870 * \param[in] t The input `IOmxBufferProducer::QueueBufferInput`.
1871 * \return The number of file descriptors contained in \p t.
1872 */
1873inline size_t getFdCount(
1874 IOmxBufferProducer::QueueBufferInput const& t) {
1875 return getFenceFdCount(t.fence);
1876}
1877
1878/**
1879 * \brief Flatten `IOmxBufferProducer::QueueBufferInput`.
1880 *
1881 * \param[in] t The source `IOmxBufferProducer::QueueBufferInput`.
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08001882 * \param[out] nh The native handle cloned from `t.fence`.
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001883 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1884 * \param[in,out] size The size of the flat non-fd buffer.
1885 * \param[in,out] fds The pointer to the flat fd buffer.
1886 * \param[in,out] numFds The size of the flat fd buffer.
1887 * \return `NO_ERROR` on success; other value on failure.
1888 *
1889 * This function will duplicate the file descriptor in `t.fence`. */
1890inline status_t flatten(IOmxBufferProducer::QueueBufferInput const& t,
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08001891 native_handle_t** nh,
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001892 void*& buffer, size_t& size, int*& fds, size_t& numFds) {
1893 if (size < getFlattenedSize(t)) {
1894 return NO_MEMORY;
1895 }
1896
1897 FlattenableUtils::write(buffer, size, t.timestamp);
1898 FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
1899 FlattenableUtils::write(buffer, size,
1900 static_cast<android_dataspace_t>(t.dataSpace));
1901 FlattenableUtils::write(buffer, size, ::android::Rect(
1902 static_cast<int32_t>(t.crop.left),
1903 static_cast<int32_t>(t.crop.top),
1904 static_cast<int32_t>(t.crop.right),
1905 static_cast<int32_t>(t.crop.bottom)));
1906 FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
1907 FlattenableUtils::write(buffer, size, t.transform);
1908 FlattenableUtils::write(buffer, size, t.stickyTransform);
1909 FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
1910
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08001911 *nh = t.fence.getNativeHandle() == nullptr ?
1912 nullptr : native_handle_clone(t.fence);
1913 status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08001914 if (status != NO_ERROR) {
1915 return status;
1916 }
1917 return flatten(t.surfaceDamage, buffer, size);
1918}
1919
1920/**
1921 * \brief Unflatten `IOmxBufferProducer::QueueBufferInput`.
1922 *
1923 * \param[out] t The destination `IOmxBufferProducer::QueueBufferInput`.
1924 * \param[out] nh The underlying native handle for `t->fence`.
1925 * \param[in,out] buffer The pointer to the flat non-fd buffer.
1926 * \param[in,out] size The size of the flat non-fd buffer.
1927 * \param[in,out] fds The pointer to the flat fd buffer.
1928 * \param[in,out] numFds The size of the flat fd buffer.
1929 * \return `NO_ERROR` on success; other value on failure.
1930 *
1931 * If the return value is `NO_ERROR` and `t->fence` contains a valid file
1932 * descriptor, \p nh will be a newly created native handle holding that file
1933 * descriptor. \p nh needs to be deleted with `native_handle_delete()`
1934 * afterwards.
1935 */
1936inline status_t unflatten(
1937 IOmxBufferProducer::QueueBufferInput* t, native_handle_t** nh,
1938 void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
1939 if (size < minFlattenedSize(*t)) {
1940 return NO_MEMORY;
1941 }
1942
1943 FlattenableUtils::read(buffer, size, t->timestamp);
1944 int lIsAutoTimestamp;
1945 FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
1946 t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
1947 android_dataspace_t lDataSpace;
1948 FlattenableUtils::read(buffer, size, lDataSpace);
1949 t->dataSpace = static_cast<Dataspace>(lDataSpace);
1950 Rect lCrop;
1951 FlattenableUtils::read(buffer, size, lCrop);
1952 t->crop = Rect{
1953 static_cast<int32_t>(lCrop.left),
1954 static_cast<int32_t>(lCrop.top),
1955 static_cast<int32_t>(lCrop.right),
1956 static_cast<int32_t>(lCrop.bottom)};
1957 int lScalingMode;
1958 FlattenableUtils::read(buffer, size, lScalingMode);
1959 t->scalingMode = static_cast<int32_t>(lScalingMode);
1960 FlattenableUtils::read(buffer, size, t->transform);
1961 FlattenableUtils::read(buffer, size, t->stickyTransform);
1962 FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
1963
1964 status_t status = unflattenFence(&(t->fence), nh,
1965 buffer, size, fds, numFds);
1966 if (status != NO_ERROR) {
1967 return status;
1968 }
1969 return unflatten(&(t->surfaceDamage), buffer, size);
1970}
1971
1972/**
1973 * \brief Wrap `IGraphicBufferProducer::QueueBufferInput` in
1974 * `IOmxBufferProducer::QueueBufferInput`.
1975 *
1976 * \param[out] t The wrapper of type
1977 * `IOmxBufferProducer::QueueBufferInput`.
1978 * \param[out] nh The underlying native handle for `t->fence`.
1979 * \param[in] l The source `IGraphicBufferProducer::QueueBufferInput`.
1980 *
1981 * If the return value is `true` and `t->fence` contains a valid file
1982 * descriptor, \p nh will be a newly created native handle holding that file
1983 * descriptor. \p nh needs to be deleted with `native_handle_delete()`
1984 * afterwards.
1985 */
1986inline bool wrapAs(
1987 IOmxBufferProducer::QueueBufferInput* t,
1988 native_handle_t** nh,
1989 IGraphicBufferProducer::QueueBufferInput const& l) {
1990
1991 size_t const baseSize = l.getFlattenedSize();
1992 std::unique_ptr<uint8_t[]> baseBuffer(
1993 new (std::nothrow) uint8_t[baseSize]);
1994 if (!baseBuffer) {
1995 return false;
1996 }
1997
1998 size_t const baseNumFds = l.getFdCount();
1999 std::unique_ptr<int[]> baseFds(
2000 new (std::nothrow) int[baseNumFds]);
2001 if (!baseFds) {
2002 return false;
2003 }
2004
2005 void* buffer = static_cast<void*>(baseBuffer.get());
2006 size_t size = baseSize;
2007 int* fds = baseFds.get();
2008 size_t numFds = baseNumFds;
2009 if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
2010 return false;
2011 }
2012
2013 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
2014 size = baseSize;
2015 int const* constFds = static_cast<int const*>(baseFds.get());
2016 numFds = baseNumFds;
2017 if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
2018 return false;
2019 }
2020
2021 return true;
2022}
2023
2024/**
2025 * \brief Convert `IOmxBufferProducer::QueueBufferInput` to
2026 * `IGraphicBufferProducer::QueueBufferInput`.
2027 *
2028 * \param[out] l The destination `IGraphicBufferProducer::QueueBufferInput`.
2029 * \param[in] t The source `IOmxBufferProducer::QueueBufferInput`.
2030 *
2031 * If `t.fence` has a valid file descriptor, it will be duplicated.
2032 */
2033inline bool convertTo(
2034 IGraphicBufferProducer::QueueBufferInput* l,
2035 IOmxBufferProducer::QueueBufferInput const& t) {
2036
2037 size_t const baseSize = getFlattenedSize(t);
2038 std::unique_ptr<uint8_t[]> baseBuffer(
2039 new (std::nothrow) uint8_t[baseSize]);
2040 if (!baseBuffer) {
2041 return false;
2042 }
2043
2044 size_t const baseNumFds = getFdCount(t);
2045 std::unique_ptr<int[]> baseFds(
2046 new (std::nothrow) int[baseNumFds]);
2047 if (!baseFds) {
2048 return false;
2049 }
2050
2051 void* buffer = static_cast<void*>(baseBuffer.get());
2052 size_t size = baseSize;
2053 int* fds = baseFds.get();
2054 size_t numFds = baseNumFds;
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08002055 native_handle_t* nh;
2056 if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08002057 return false;
2058 }
2059
2060 void const* constBuffer = static_cast<void const*>(baseBuffer.get());
2061 size = baseSize;
2062 int const* constFds = static_cast<int const*>(baseFds.get());
2063 numFds = baseNumFds;
2064 if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08002065 native_handle_close(nh);
2066 native_handle_delete(nh);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08002067 return false;
2068 }
2069
Pawin Vongmasa8b13a002017-02-24 06:06:43 -08002070 native_handle_delete(nh);
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08002071 return true;
2072}
2073
2074// Ref: frameworks/native/libs/gui/IGraphicBufferProducer.cpp:
2075// IGraphicBufferProducer::QueueBufferOutput
2076
2077/**
2078 * \brief Wrap `IGraphicBufferProducer::QueueBufferOutput` in
2079 * `IOmxBufferProducer::QueueBufferOutput`.
2080 *
2081 * \param[out] t The wrapper of type
2082 * `IOmxBufferProducer::QueueBufferOutput`.
2083 * \param[out] nh The array of array of native handles that are referred to by
2084 * members of \p t.
2085 * \param[in] l The source `IGraphicBufferProducer::QueueBufferOutput`.
2086 *
2087 * On success, each member of \p nh will be either `nullptr` or a newly created
2088 * native handle. All the non-`nullptr` elements must be deleted individually
2089 * with `native_handle_delete()`.
2090 */
2091// wrap: IGraphicBufferProducer::QueueBufferOutput ->
2092// IOmxBufferProducer::QueueBufferOutput
2093inline bool wrapAs(IOmxBufferProducer::QueueBufferOutput* t,
2094 std::vector<std::vector<native_handle_t*> >* nh,
2095 IGraphicBufferProducer::QueueBufferOutput const& l) {
2096 if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
2097 return false;
2098 }
2099 t->width = l.width;
2100 t->height = l.height;
2101 t->transformHint = l.transformHint;
2102 t->numPendingBuffers = l.numPendingBuffers;
2103 t->nextFrameNumber = l.nextFrameNumber;
Pawin Vongmasa92b6b722017-02-06 19:06:39 -08002104 t->bufferReplaced = l.bufferReplaced;
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08002105 return true;
2106}
2107
2108/**
2109 * \brief Convert `IOmxBufferProducer::QueueBufferOutput` to
2110 * `IGraphicBufferProducer::QueueBufferOutput`.
2111 *
2112 * \param[out] l The destination `IGraphicBufferProducer::QueueBufferOutput`.
2113 * \param[in] t The source `IOmxBufferProducer::QueueBufferOutput`.
2114 *
2115 * This function will duplicate all file descriptors contained in \p t.
2116 */
2117// convert: IOmxBufferProducer::QueueBufferOutput ->
2118// IGraphicBufferProducer::QueueBufferOutput
2119inline bool convertTo(
2120 IGraphicBufferProducer::QueueBufferOutput* l,
2121 IOmxBufferProducer::QueueBufferOutput const& t) {
2122 if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
2123 return false;
2124 }
2125 l->width = t.width;
2126 l->height = t.height;
2127 l->transformHint = t.transformHint;
2128 l->numPendingBuffers = t.numPendingBuffers;
2129 l->nextFrameNumber = t.nextFrameNumber;
Pawin Vongmasa92b6b722017-02-06 19:06:39 -08002130 l->bufferReplaced = t.bufferReplaced;
Pawin Vongmasaeeac97b2017-01-18 05:03:07 -08002131 return true;
2132}
2133
2134/**
2135 * \brief Convert `IGraphicBufferProducer::DisconnectMode` to
2136 * `IOmxBufferProducer::DisconnectMode`.
2137 *
2138 * \param[in] l The source `IGraphicBufferProducer::DisconnectMode`.
2139 * \return The corresponding `IOmxBufferProducer::DisconnectMode`.
2140 */
2141inline IOmxBufferProducer::DisconnectMode toOmxDisconnectMode(
2142 IGraphicBufferProducer::DisconnectMode l) {
2143 switch (l) {
2144 case IGraphicBufferProducer::DisconnectMode::Api:
2145 return IOmxBufferProducer::DisconnectMode::API;
2146 case IGraphicBufferProducer::DisconnectMode::AllLocal:
2147 return IOmxBufferProducer::DisconnectMode::ALL_LOCAL;
2148 }
2149 return IOmxBufferProducer::DisconnectMode::API;
2150}
2151
2152/**
2153 * \brief Convert `IOmxBufferProducer::DisconnectMode` to
2154 * `IGraphicBufferProducer::DisconnectMode`.
2155 *
2156 * \param[in] l The source `IOmxBufferProducer::DisconnectMode`.
2157 * \return The corresponding `IGraphicBufferProducer::DisconnectMode`.
2158 */
2159inline IGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
2160 IOmxBufferProducer::DisconnectMode t) {
2161 switch (t) {
2162 case IOmxBufferProducer::DisconnectMode::API:
2163 return IGraphicBufferProducer::DisconnectMode::Api;
2164 case IOmxBufferProducer::DisconnectMode::ALL_LOCAL:
2165 return IGraphicBufferProducer::DisconnectMode::AllLocal;
2166 }
2167 return IGraphicBufferProducer::DisconnectMode::Api;
2168}
2169
2170} // namespace utils
2171} // namespace V1_0
2172} // namespace omx
2173} // namespace media
2174} // namespace hardware
2175} // namespace android
2176
2177#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H