status_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
    if (size < getFlattenedSize() || count < getFdCount()) {
        return NO_MEMORY;
    }
    FlattenableUtils::write(buffer, size, (uint32_t)getFdCount());
    if (isValid()) {
        *fds++ = mFenceFd;
        count--;
    }
    return NO_ERROR;
}
/**
 * \brief Return the number of file descriptors contained in
 * `HGraphicBufferProducer::FrameEventHistoryDelta`.
 *
 * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
 * \return The number of file descriptors contained in \p t.
 */
inline size_t getFdCount(
        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
    size_t numFds = 0;
    for (size_t i = 0; i < t.deltas.size(); ++i) {
        numFds += getFdCount(t.deltas[i]);
    }
    return numFds;
}
/**
 * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
 * `::android::FrameEventHistoryDelta`.
 *
 * \param[out] l The destination `::android::FrameEventHistoryDelta`.
 * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
 *
 * This function will duplicate all file descriptors contained in \p t.
 */
inline bool convertTo(
        ::android::FrameEventHistoryDelta* l,
        HGraphicBufferProducer::FrameEventHistoryDelta const& t) {

    size_t const baseSize = getFlattenedSize(t);
    std::unique_ptr<uint8_t[]> baseBuffer(
            new (std::nothrow) uint8_t[baseSize]);
    if (!baseBuffer) {
        return false;
    }

    size_t const baseNumFds = getFdCount(t);
    std::unique_ptr<int[]> baseFds(
            new (std::nothrow) int[baseNumFds]);
    if (!baseFds) {
        return false;
    }

    void* buffer = static_cast<void*>(baseBuffer.get());
    size_t size = baseSize;
    int* fds = static_cast<int*>(baseFds.get());
    size_t numFds = baseNumFds;
    std::vector<std::vector<native_handle_t*> > nhAA;
    if (flatten(t, &nhAA, buffer, size, fds, numFds) != NO_ERROR) {
        return false;
    }

    void const* constBuffer = static_cast<void const*>(baseBuffer.get());
    size = baseSize;
    int const* constFds = static_cast<int const*>(baseFds.get());
    numFds = baseNumFds;
    if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
        for (auto nhA : nhAA) {
            for (auto nh : nhA) {
                if (nh != nullptr) {
                    native_handle_close(nh);
                    native_handle_delete(nh);
                }
            }
        }
        return false;
    }

    for (auto nhA : nhAA) {
        for (auto nh : nhA) {
            if (nh != nullptr) {
                native_handle_delete(nh);
            }
        }
    }
    return true;
}
static jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);

    CursorWindow* window;
    status_t status = CursorWindow::createFromParcel(parcel, &window);
    if (status || !window) {
        ALOGE("Could not create CursorWindow from Parcel due to error %d, process fd count=%d",
                status, getFdCount());
        return 0;
    }

    LOG_WINDOW("nativeInitializeFromBinder: numRows = %d, numColumns = %d, window = %p",
            window->getNumRows(), window->getNumColumns(), window);
    return reinterpret_cast<jlong>(window);
}