void serializeLayer(LayerAndroid* layer, SkWStream* stream)
{
    if (!layer) {
        ALOGV("NULL layer!");
        stream->write8(LTNone);
        return;
    }
    if (layer->isMedia() || layer->isVideo()) {
        ALOGV("Layer isn't supported for serialization: isMedia: %s, isVideo: %s",
             layer->isMedia() ? "true" : "false",
             layer->isVideo() ? "true" : "false");
        stream->write8(LTNone);
        return;
    }
    LayerTypes type = LTLayerAndroid;
    if (layer->contentIsScrollable())
        type = LTScrollableLayerAndroid;
    stream->write8(type);

    // Start with Layer fields
    stream->writeBool(layer->shouldInheritFromRootTransform());
    stream->writeScalar(layer->getOpacity());
    stream->writeScalar(layer->getSize().width());
    stream->writeScalar(layer->getSize().height());
    stream->writeScalar(layer->getPosition().x());
    stream->writeScalar(layer->getPosition().y());
    stream->writeScalar(layer->getAnchorPoint().x());
    stream->writeScalar(layer->getAnchorPoint().y());
    writeMatrix(stream, layer->getMatrix());
    writeMatrix(stream, layer->getChildrenMatrix());

    // Next up, LayerAndroid fields
    stream->writeBool(layer->m_haveClip);
    stream->writeBool(layer->isPositionFixed());
    stream->writeBool(layer->m_backgroundColorSet);
    stream->writeBool(layer->isIFrame());

    // With the current LayerAndroid hierarchy, LayerAndroid doesn't have
    // those fields anymore. Let's keep the current serialization format for
    // now and output blank fields... not great, but probably better than
    // dealing with multiple versions.
    if (layer->fixedPosition()) {
        FixedPositioning* fixedPosition = layer->fixedPosition();
        writeSkLength(stream, fixedPosition->m_fixedLeft);
        writeSkLength(stream, fixedPosition->m_fixedTop);
        writeSkLength(stream, fixedPosition->m_fixedRight);
        writeSkLength(stream, fixedPosition->m_fixedBottom);
        writeSkLength(stream, fixedPosition->m_fixedMarginLeft);
        writeSkLength(stream, fixedPosition->m_fixedMarginTop);
        writeSkLength(stream, fixedPosition->m_fixedMarginRight);
        writeSkLength(stream, fixedPosition->m_fixedMarginBottom);
        writeSkRect(stream, fixedPosition->m_fixedRect);
        stream->write32(fixedPosition->m_renderLayerPos.x());
        stream->write32(fixedPosition->m_renderLayerPos.y());
    } else {
        SkLength length;
        SkRect rect;
        writeSkLength(stream, length); // fixedLeft
        writeSkLength(stream, length); // fixedTop
        writeSkLength(stream, length); // fixedRight
        writeSkLength(stream, length); // fixedBottom
        writeSkLength(stream, length); // fixedMarginLeft
        writeSkLength(stream, length); // fixedMarginTop
        writeSkLength(stream, length); // fixedMarginRight
        writeSkLength(stream, length); // fixedMarginBottom
        writeSkRect(stream, rect);     // fixedRect
        stream->write32(0);            // renderLayerPos.x()
        stream->write32(0);            // renderLayerPos.y()
    }

    stream->writeBool(layer->m_backfaceVisibility);
    stream->writeBool(layer->m_visible);
    stream->write32(layer->m_backgroundColor);
    stream->writeBool(layer->m_preserves3D);
    stream->writeScalar(layer->m_anchorPointZ);
    stream->writeScalar(layer->m_drawOpacity);
    bool hasContentsImage = layer->m_imageCRC != 0;
    stream->writeBool(hasContentsImage);
    if (hasContentsImage) {
        SkFlattenableWriteBuffer buffer(1024);
        buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
        ImageTexture* imagetexture =
                ImagesManager::instance()->retainImage(layer->m_imageCRC);
        if (imagetexture && imagetexture->bitmap())
            imagetexture->bitmap()->flatten(buffer);
        ImagesManager::instance()->releaseImage(layer->m_imageCRC);
        stream->write32(buffer.size());
        buffer.writeToStream(stream);
    }
    bool hasRecordingPicture = layer->m_content != 0 && !layer->m_content->isEmpty();
    stream->writeBool(hasRecordingPicture);
    if (hasRecordingPicture)
        layer->m_content->serialize(stream);
    // TODO: support m_animations (maybe?)
    stream->write32(0); // placeholder for m_animations.size();
    writeTransformationMatrix(stream, layer->m_transform);
    writeTransformationMatrix(stream, layer->m_childrenTransform);
    if (type == LTScrollableLayerAndroid) {
        ScrollableLayerAndroid* scrollableLayer =
                static_cast<ScrollableLayerAndroid*>(layer);
        stream->writeScalar(scrollableLayer->m_scrollLimits.fLeft);
        stream->writeScalar(scrollableLayer->m_scrollLimits.fTop);
        stream->writeScalar(scrollableLayer->m_scrollLimits.width());
        stream->writeScalar(scrollableLayer->m_scrollLimits.height());
    }
    int childCount = layer->countChildren();
    stream->write32(childCount);
    for (int i = 0; i < childCount; i++)
        serializeLayer(layer->getChild(i), stream);
}
void serializeLayer(LayerAndroid* layer, SkWStream* stream)
{
    if (!layer) {
        XLOG("NULL layer!");
        stream->write8(LTNone);
        return;
    }
    if (layer->isMedia() || layer->isVideo()) {
        XLOG("Layer isn't supported for serialization: isMedia: %s, isVideo: %s",
             layer->isMedia() ? "true" : "false",
             layer->isVideo() ? "true" : "false");
        stream->write8(LTNone);
        return;
    }
    LayerTypes type = layer->contentIsScrollable()
            ? LTScrollableLayerAndroid
            : LTLayerAndroid;
    stream->write8(type);

    // Start with Layer fields
    stream->writeBool(layer->shouldInheritFromRootTransform());
    stream->writeScalar(layer->getOpacity());
    stream->writeScalar(layer->getSize().width());
    stream->writeScalar(layer->getSize().height());
    stream->writeScalar(layer->getPosition().x());
    stream->writeScalar(layer->getPosition().y());
    stream->writeScalar(layer->getAnchorPoint().x());
    stream->writeScalar(layer->getAnchorPoint().y());
    writeMatrix(stream, layer->getMatrix());
    writeMatrix(stream, layer->getChildrenMatrix());

    // Next up, LayerAndroid fields
    stream->writeBool(layer->m_haveClip);
    stream->writeBool(layer->m_isFixed);
    stream->writeBool(layer->m_backgroundColorSet);
    stream->writeBool(layer->m_isIframe);
    writeSkLength(stream, layer->m_fixedLeft);
    writeSkLength(stream, layer->m_fixedTop);
    writeSkLength(stream, layer->m_fixedRight);
    writeSkLength(stream, layer->m_fixedBottom);
    writeSkLength(stream, layer->m_fixedMarginLeft);
    writeSkLength(stream, layer->m_fixedMarginTop);
    writeSkLength(stream, layer->m_fixedMarginRight);
    writeSkLength(stream, layer->m_fixedMarginBottom);
    writeSkRect(stream, layer->m_fixedRect);
    stream->write32(layer->m_renderLayerPos.x());
    stream->write32(layer->m_renderLayerPos.y());
    stream->writeBool(layer->m_backfaceVisibility);
    stream->writeBool(layer->m_visible);
    stream->write32(layer->m_backgroundColor);
    stream->writeBool(layer->m_preserves3D);
    stream->writeScalar(layer->m_anchorPointZ);
    stream->writeScalar(layer->m_drawOpacity);
    bool hasContentsImage = layer->m_imageCRC != 0;
    stream->writeBool(hasContentsImage);
    if (hasContentsImage) {
        SkFlattenableWriteBuffer buffer(1024);
        buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
        ImageTexture* imagetexture =
                ImagesManager::instance()->retainImage(layer->m_imageCRC);
        if (imagetexture && imagetexture->bitmap())
            imagetexture->bitmap()->flatten(buffer);
        ImagesManager::instance()->releaseImage(layer->m_imageCRC);
        stream->write32(buffer.size());
        buffer.writeToStream(stream);
    }
    bool hasRecordingPicture = layer->m_recordingPicture != 0;
    stream->writeBool(hasRecordingPicture);
    if (hasRecordingPicture)
        layer->m_recordingPicture->serialize(stream);
    // TODO: support m_animations (maybe?)
    stream->write32(0); // placeholder for m_animations.size();
    writeTransformationMatrix(stream, layer->m_transform);
    writeTransformationMatrix(stream, layer->m_childrenTransform);
    if (type == LTScrollableLayerAndroid) {
        ScrollableLayerAndroid* scrollableLayer =
                static_cast<ScrollableLayerAndroid*>(layer);
        stream->writeScalar(scrollableLayer->m_scrollLimits.fLeft);
        stream->writeScalar(scrollableLayer->m_scrollLimits.fTop);
        stream->writeScalar(scrollableLayer->m_scrollLimits.width());
        stream->writeScalar(scrollableLayer->m_scrollLimits.height());
    }
    int childCount = layer->countChildren();
    stream->write32(childCount);
    for (int i = 0; i < childCount; i++)
        serializeLayer(layer->getChild(i), stream);
}