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