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