// This is called on the UI thread only.
// The video layers are composited on the webkit thread and then copied over
// to the UI thread with the same ID. For rendering, we are only using the
// video layers on the UI thread. Therefore, on the UI thread, we have to use
// the videoLayerId from Java side to find the exact video layer in the tree
// to set the surface texture.
// Every time a play call into Java side, the videoLayerId will be sent and
// saved in Java side. Then every time setBaseLayer call, the saved
// videoLayerId will be passed to this function to find the Video Layer.
// Return value: true when the video layer is found.
static bool SendSurfaceTexture(JNIEnv* env, jobject obj, jobject surfTex,
                               int baseLayer, int videoLayerId,
                               int textureName, int playerState) {
    if (!surfTex)
        return false;

    sp<SurfaceTexture> texture = android::SurfaceTexture_getSurfaceTexture(env, surfTex);
    if (!texture.get())
        return false;

    BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(baseLayer);
    if (!layerImpl)
        return false;
    if (!layerImpl->countChildren())
        return false;
    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(layerImpl->getChild(0));
    if (!compositedRoot)
        return false;

    VideoLayerAndroid* videoLayer =
        static_cast<VideoLayerAndroid*>(compositedRoot->findById(videoLayerId));
    if (!videoLayer)
        return false;

    // Set the SurfaceTexture to the layer we found
    videoLayer->setSurfaceTexture(texture, textureName, static_cast<PlayerState>(playerState));
    return true;
}
// draw for base tile - called on TextureGeneration thread
void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
{
    BaseLayerAndroid* paintingTree = 0;
    m_paintSwapLock.lock();
    if (m_paintingTree)
        paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
    else
        paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
    SkSafeRef(paintingTree);
    m_paintSwapLock.unlock();

    if (!paintingTree)
        return;


    paintingTree->drawCanvas(canvas);

    if (drawLayers && paintingTree->countChildren()) {
        // draw the layers onto the canvas as well
        Layer* layers = paintingTree->getChild(0);
        static_cast<LayerAndroid*>(layers)->drawCanvas(canvas);
    }

    SkSafeUnref(paintingTree);
}
static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jint version,
                                                    jobject jstream, jbyteArray jstorage)
{
    SkStream* stream = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
    if (!stream)
        return 0;
    Color color = stream->readU32();
    SkPicture* picture = new SkPicture(stream);
    PictureLayerContent* content = new PictureLayerContent(picture);

    BaseLayerAndroid* layer = new BaseLayerAndroid(content);
    layer->setBackgroundColor(color);

    SkRegion dirtyRegion;
    dirtyRegion.setRect(0, 0, content->width(), content->height());
    layer->markAsDirty(dirtyRegion);

    SkSafeUnref(content);
    SkSafeUnref(picture);
    int childCount = stream->readS32();
    for (int i = 0; i < childCount; i++) {
        LayerAndroid* childLayer = deserializeLayer(version, stream);
        if (childLayer)
            layer->addChild(childLayer);
    }
    delete stream;
    return layer;
}
static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobject jstream,
                                      jbyteArray jstorage)
{
    SkStream* stream = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
    if (!stream)
        return 0;
    BaseLayerAndroid* layer = new BaseLayerAndroid();
// SAMSUNG CHANGE >> White flickering issue.
// WAS:Color color = stream->readU32();
    SkColor color = stream->readU32();
// SAMSUNG CHANGE <<
#if USE(ACCELERATED_COMPOSITING)
    layer->setBackgroundColor(color);
#endif
    SkPicture* picture = new SkPicture(stream);
    layer->setContent(picture);
    SkSafeUnref(picture);
    int childCount = stream->readS32();
    for (int i = 0; i < childCount; i++) {
        LayerAndroid* childLayer = deserializeLayer(stream);
        if (childLayer)
            layer->addChild(childLayer);
    }
    delete stream;
    return layer;
}
static void nativeDumpLayerHierarchy(JNIEnv* env, jobject, jint jbaseLayer, jint level,
                                     jobject jstream, jbyteArray jstorage)
{
    SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
    BaseLayerAndroid* baseLayer = reinterpret_cast<BaseLayerAndroid*>(jbaseLayer);
    SkSafeRef(baseLayer);
    HierarchyLayerDumper dumper(stream, level);
    baseLayer->dumpLayers(&dumper);
    SkSafeUnref(baseLayer);
    delete stream;
}
static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
                                     jobject jstream, jbyteArray jstorage)
{
    BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer;
    if (!baseLayer)
        return false;

    SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
#if USE(ACCELERATED_COMPOSITING)
    stream->write32(baseLayer->getBackgroundColor().rgb());
#else
    stream->write32(0);
#endif
    if (!stream)
        return false;
    if (baseLayer->content())
        baseLayer->content()->serialize(stream);
    else
        return false;
    int childCount = baseLayer->countChildren();
    ALOGV("BaseLayer has %d child(ren)", childCount);
    stream->write32(childCount);
    for (int i = 0; i < childCount; i++) {
        LayerAndroid* layer = static_cast<LayerAndroid*>(baseLayer->getChild(i));
        serializeLayer(layer, stream);
    }
    delete stream;
    return true;
}
static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
                                     jobject jstream, jbyteArray jstorage)
{
    BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer;
    if (!baseLayer)
        return false;

    SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
#if USE(ACCELERATED_COMPOSITING)
// SAMSUNG CHANGE >> White flickering issue.
// WAS:stream->write32(baseLayer->getBackgroundColor().rgb());
    stream->write32(baseLayer->getBackgroundColor());
// SAMSUNG CHANGE <<
#else
    stream->write32(0);
#endif
    SkPicture picture;
    PictureSet* content = baseLayer->content();
    baseLayer->drawCanvas(picture.beginRecording(content->width(), content->height(),
            SkPicture::kUsePathBoundsForClip_RecordingFlag));
    picture.endRecording();
    if (!stream)
        return false;
    picture.serialize(stream);
    int childCount = baseLayer->countChildren();
    XLOG("BaseLayer has %d child(ren)", childCount);
    stream->write32(childCount);
    for (int i = 0; i < childCount; i++) {
        LayerAndroid* layer = static_cast<LayerAndroid*>(baseLayer->getChild(i));
        serializeLayer(layer, stream);
    }
    delete stream;
    return true;
}
// This is called on the UI thread only.
// The video layers are composited on the webkit thread and then copied over
// to the UI thread with the same ID. For rendering, we are only using the
// video layers on the UI thread. Therefore, on the UI thread, we have to use
// the videoLayerId from Java side to find the exact video layer in the tree
// to set the surface texture.
// Every time a play call into Java side, the videoLayerId will be sent and
// saved in Java side. Then every time setBaseLayer call, the saved
// videoLayerId will be passed to this function to find the Video Layer.
// Return value: true when the video layer is found.
static bool SendSurfaceTexture(JNIEnv* env, jobject obj, jobject surfTex,
                               int baseLayer, int videoLayerId,
                               int textureName, int playerState) {
    if (!surfTex)
        return false;

    sp<GLConsumer> texture = android::SurfaceTexture_getSurfaceTexture(env, surfTex);
    if (!texture.get())
        return false;

    BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(baseLayer);
    if (!layerImpl)
        return false;

    VideoLayerAndroid* videoLayer =
        static_cast<VideoLayerAndroid*>(layerImpl->findById(videoLayerId));
    if (!videoLayer)
        return false;

    // Set the GLConsumer to the layer we found
    videoLayer->setSurfaceTexture(texture, textureName, static_cast<PlayerState>(playerState));
    return true;
}