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