1/*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#define LOG_TAG "ViewStateSerializer"
27#define LOG_NDEBUG 1
28
29#include "config.h"
30
31#include "BaseLayerAndroid.h"
32#include "CreateJavaOutputStreamAdaptor.h"
33#include "DumpLayer.h"
34#include "FixedPositioning.h"
35#include "ImagesManager.h"
36#include "IFrameContentLayerAndroid.h"
37#include "IFrameLayerAndroid.h"
38#include "Layer.h"
39#include "LayerAndroid.h"
40#include "LayerContent.h"
41#include "PictureLayerContent.h"
42#include "ScrollableLayerAndroid.h"
43#include "SkFlattenable.h"
44#include "SkPicture.h"
45#include "TilesManager.h"
46
47#include <JNIUtility.h>
48#include <JNIHelp.h>
49#include <jni.h>
50
51namespace android {
52
53enum LayerTypes {
54    LTNone = 0,
55    LTLayerAndroid = 1,
56    LTScrollableLayerAndroid = 2,
57    LTFixedLayerAndroid = 3
58};
59
60#define ID "mID"
61#define LEFT "layout:mLeft"
62#define TOP "layout:mTop"
63#define WIDTH "layout:getWidth()"
64#define HEIGHT "layout:getHeight()"
65
66class HierarchyLayerDumper : public LayerDumper {
67public:
68    HierarchyLayerDumper(SkWStream* stream, int level)
69        : LayerDumper(level)
70        , m_stream(stream)
71    {}
72
73    virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) {
74        LayerDumper::beginLayer(className, layerPtr);
75        for (int i = 0; i < m_indentLevel; i++) {
76            m_stream->writeText(" ");
77        }
78        m_stream->writeText(className);
79        m_stream->writeText("@");
80        m_stream->writeHexAsText(layerPtr->uniqueId());
81        m_stream->writeText(" ");
82
83        writeHexVal(ID, (int) layerPtr);
84        writeIntVal(LEFT, layerPtr->getPosition().fX);
85        writeIntVal(TOP, layerPtr->getPosition().fY);
86        writeIntVal(WIDTH, layerPtr->getWidth());
87        writeIntVal(HEIGHT, layerPtr->getHeight());
88    }
89
90    virtual void beginChildren(int childCount) {
91        m_stream->writeText("\n");
92        LayerDumper::beginChildren(childCount);
93    }
94
95protected:
96    virtual void writeEntry(const char* label, const char* value) {
97        m_stream->writeText(label);
98        m_stream->writeText("=");
99        int len = strlen(value);
100        m_stream->writeDecAsText(len);
101        m_stream->writeText(",");
102        m_stream->writeText(value);
103        m_stream->writeText(" ");
104    }
105
106private:
107    SkWStream* m_stream;
108};
109
110static void nativeDumpLayerHierarchy(JNIEnv* env, jobject, jint jbaseLayer, jint level,
111                                     jobject jstream, jbyteArray jstorage)
112{
113    SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
114    BaseLayerAndroid* baseLayer = reinterpret_cast<BaseLayerAndroid*>(jbaseLayer);
115    SkSafeRef(baseLayer);
116    HierarchyLayerDumper dumper(stream, level);
117    baseLayer->dumpLayers(&dumper);
118    SkSafeUnref(baseLayer);
119    delete stream;
120}
121
122static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
123                                     jobject jstream, jbyteArray jstorage)
124{
125    BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer;
126    if (!baseLayer)
127        return false;
128
129    SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
130#if USE(ACCELERATED_COMPOSITING)
131    stream->write32(baseLayer->getBackgroundColor().rgb());
132#else
133    stream->write32(0);
134#endif
135    if (!stream)
136        return false;
137    if (baseLayer->content())
138        baseLayer->content()->serialize(stream);
139    else
140        return false;
141    int childCount = baseLayer->countChildren();
142    ALOGV("BaseLayer has %d child(ren)", childCount);
143    stream->write32(childCount);
144    for (int i = 0; i < childCount; i++) {
145        LayerAndroid* layer = static_cast<LayerAndroid*>(baseLayer->getChild(i));
146        serializeLayer(layer, stream);
147    }
148    delete stream;
149    return true;
150}
151
152static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jint version,
153                                                    jobject jstream, jbyteArray jstorage)
154{
155    SkStream* stream = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
156    if (!stream)
157        return 0;
158    Color color = stream->readU32();
159    SkPicture* picture = new SkPicture(stream);
160    PictureLayerContent* content = new PictureLayerContent(picture);
161
162    BaseLayerAndroid* layer = new BaseLayerAndroid(content);
163    layer->setBackgroundColor(color);
164
165    SkRegion dirtyRegion;
166    dirtyRegion.setRect(0, 0, content->width(), content->height());
167    layer->markAsDirty(dirtyRegion);
168
169    SkSafeUnref(content);
170    SkSafeUnref(picture);
171    int childCount = stream->readS32();
172    for (int i = 0; i < childCount; i++) {
173        LayerAndroid* childLayer = deserializeLayer(version, stream);
174        if (childLayer)
175            layer->addChild(childLayer);
176    }
177    delete stream;
178    return layer;
179}
180
181// Serialization helpers
182
183void writeMatrix(SkWStream *stream, const SkMatrix& matrix)
184{
185    for (int i = 0; i < 9; i++)
186        stream->writeScalar(matrix[i]);
187}
188
189SkMatrix readMatrix(SkStream *stream)
190{
191    SkMatrix matrix;
192    for (int i = 0; i < 9; i++)
193        matrix.set(i, stream->readScalar());
194    return matrix;
195}
196
197void writeSkLength(SkWStream *stream, SkLength length)
198{
199    stream->write32(length.type);
200    stream->writeScalar(length.value);
201}
202
203SkLength readSkLength(SkStream *stream)
204{
205    SkLength len;
206    len.type = (SkLength::SkLengthType) stream->readU32();
207    len.value = stream->readScalar();
208    return len;
209}
210
211void writeSkRect(SkWStream *stream, SkRect rect)
212{
213    stream->writeScalar(rect.fLeft);
214    stream->writeScalar(rect.fTop);
215    stream->writeScalar(rect.fRight);
216    stream->writeScalar(rect.fBottom);
217}
218
219SkRect readSkRect(SkStream *stream)
220{
221    SkRect rect;
222    rect.fLeft = stream->readScalar();
223    rect.fTop = stream->readScalar();
224    rect.fRight = stream->readScalar();
225    rect.fBottom = stream->readScalar();
226    return rect;
227}
228
229void writeTransformationMatrix(SkWStream *stream, TransformationMatrix& matrix)
230{
231    double value;
232    int dsize = sizeof(double);
233    value = matrix.m11();
234    stream->write(&value, dsize);
235    value = matrix.m12();
236    stream->write(&value, dsize);
237    value = matrix.m13();
238    stream->write(&value, dsize);
239    value = matrix.m14();
240    stream->write(&value, dsize);
241    value = matrix.m21();
242    stream->write(&value, dsize);
243    value = matrix.m22();
244    stream->write(&value, dsize);
245    value = matrix.m23();
246    stream->write(&value, dsize);
247    value = matrix.m24();
248    stream->write(&value, dsize);
249    value = matrix.m31();
250    stream->write(&value, dsize);
251    value = matrix.m32();
252    stream->write(&value, dsize);
253    value = matrix.m33();
254    stream->write(&value, dsize);
255    value = matrix.m34();
256    stream->write(&value, dsize);
257    value = matrix.m41();
258    stream->write(&value, dsize);
259    value = matrix.m42();
260    stream->write(&value, dsize);
261    value = matrix.m43();
262    stream->write(&value, dsize);
263    value = matrix.m44();
264    stream->write(&value, dsize);
265}
266
267void readTransformationMatrix(SkStream *stream, TransformationMatrix& matrix)
268{
269    double value;
270    int dsize = sizeof(double);
271    stream->read(&value, dsize);
272    matrix.setM11(value);
273    stream->read(&value, dsize);
274    matrix.setM12(value);
275    stream->read(&value, dsize);
276    matrix.setM13(value);
277    stream->read(&value, dsize);
278    matrix.setM14(value);
279    stream->read(&value, dsize);
280    matrix.setM21(value);
281    stream->read(&value, dsize);
282    matrix.setM22(value);
283    stream->read(&value, dsize);
284    matrix.setM23(value);
285    stream->read(&value, dsize);
286    matrix.setM24(value);
287    stream->read(&value, dsize);
288    matrix.setM31(value);
289    stream->read(&value, dsize);
290    matrix.setM32(value);
291    stream->read(&value, dsize);
292    matrix.setM33(value);
293    stream->read(&value, dsize);
294    matrix.setM34(value);
295    stream->read(&value, dsize);
296    matrix.setM41(value);
297    stream->read(&value, dsize);
298    matrix.setM42(value);
299    stream->read(&value, dsize);
300    matrix.setM43(value);
301    stream->read(&value, dsize);
302    matrix.setM44(value);
303}
304
305void serializeLayer(LayerAndroid* layer, SkWStream* stream)
306{
307    if (!layer) {
308        ALOGV("NULL layer!");
309        stream->write8(LTNone);
310        return;
311    }
312    if (layer->isMedia() || layer->isVideo()) {
313        ALOGV("Layer isn't supported for serialization: isMedia: %s, isVideo: %s",
314             layer->isMedia() ? "true" : "false",
315             layer->isVideo() ? "true" : "false");
316        stream->write8(LTNone);
317        return;
318    }
319    LayerTypes type = LTLayerAndroid;
320    if (layer->contentIsScrollable())
321        type = LTScrollableLayerAndroid;
322    stream->write8(type);
323
324    // Start with Layer fields
325    stream->writeBool(layer->shouldInheritFromRootTransform());
326    stream->writeScalar(layer->getOpacity());
327    stream->writeScalar(layer->getSize().width());
328    stream->writeScalar(layer->getSize().height());
329    stream->writeScalar(layer->getPosition().x());
330    stream->writeScalar(layer->getPosition().y());
331    stream->writeScalar(layer->getAnchorPoint().x());
332    stream->writeScalar(layer->getAnchorPoint().y());
333    writeMatrix(stream, layer->getMatrix());
334    writeMatrix(stream, layer->getChildrenMatrix());
335
336    // Next up, LayerAndroid fields
337    stream->writeBool(layer->m_haveClip);
338    stream->writeBool(layer->isPositionFixed());
339    stream->writeBool(layer->m_backgroundColorSet);
340    stream->writeBool(layer->isIFrame());
341
342    // With the current LayerAndroid hierarchy, LayerAndroid doesn't have
343    // those fields anymore. Let's keep the current serialization format for
344    // now and output blank fields... not great, but probably better than
345    // dealing with multiple versions.
346    if (layer->fixedPosition()) {
347        FixedPositioning* fixedPosition = layer->fixedPosition();
348        writeSkLength(stream, fixedPosition->m_fixedLeft);
349        writeSkLength(stream, fixedPosition->m_fixedTop);
350        writeSkLength(stream, fixedPosition->m_fixedRight);
351        writeSkLength(stream, fixedPosition->m_fixedBottom);
352        writeSkLength(stream, fixedPosition->m_fixedMarginLeft);
353        writeSkLength(stream, fixedPosition->m_fixedMarginTop);
354        writeSkLength(stream, fixedPosition->m_fixedMarginRight);
355        writeSkLength(stream, fixedPosition->m_fixedMarginBottom);
356        writeSkRect(stream, fixedPosition->m_fixedRect);
357        stream->write32(fixedPosition->m_renderLayerPos.x());
358        stream->write32(fixedPosition->m_renderLayerPos.y());
359    } else {
360        SkLength length;
361        SkRect rect;
362        writeSkLength(stream, length); // fixedLeft
363        writeSkLength(stream, length); // fixedTop
364        writeSkLength(stream, length); // fixedRight
365        writeSkLength(stream, length); // fixedBottom
366        writeSkLength(stream, length); // fixedMarginLeft
367        writeSkLength(stream, length); // fixedMarginTop
368        writeSkLength(stream, length); // fixedMarginRight
369        writeSkLength(stream, length); // fixedMarginBottom
370        writeSkRect(stream, rect);     // fixedRect
371        stream->write32(0);            // renderLayerPos.x()
372        stream->write32(0);            // renderLayerPos.y()
373    }
374
375    stream->writeBool(layer->m_backfaceVisibility);
376    stream->writeBool(layer->m_visible);
377    stream->write32(layer->m_backgroundColor);
378    stream->writeBool(layer->m_preserves3D);
379    stream->writeScalar(layer->m_anchorPointZ);
380    stream->writeScalar(layer->m_drawOpacity);
381    bool hasContentsImage = layer->m_imageCRC != 0;
382    stream->writeBool(hasContentsImage);
383    if (hasContentsImage) {
384        SkFlattenableWriteBuffer buffer(1024);
385        buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
386        ImageTexture* imagetexture =
387                ImagesManager::instance()->retainImage(layer->m_imageCRC);
388        if (imagetexture && imagetexture->bitmap())
389            imagetexture->bitmap()->flatten(buffer);
390        ImagesManager::instance()->releaseImage(layer->m_imageCRC);
391        stream->write32(buffer.size());
392        buffer.writeToStream(stream);
393    }
394    bool hasRecordingPicture = layer->m_content != 0 && !layer->m_content->isEmpty();
395    stream->writeBool(hasRecordingPicture);
396    if (hasRecordingPicture)
397        layer->m_content->serialize(stream);
398    // TODO: support m_animations (maybe?)
399    stream->write32(0); // placeholder for m_animations.size();
400    writeTransformationMatrix(stream, layer->m_transform);
401    writeTransformationMatrix(stream, layer->m_childrenTransform);
402    if (type == LTScrollableLayerAndroid) {
403        ScrollableLayerAndroid* scrollableLayer =
404                static_cast<ScrollableLayerAndroid*>(layer);
405        stream->writeScalar(scrollableLayer->m_scrollLimits.fLeft);
406        stream->writeScalar(scrollableLayer->m_scrollLimits.fTop);
407        stream->writeScalar(scrollableLayer->m_scrollLimits.width());
408        stream->writeScalar(scrollableLayer->m_scrollLimits.height());
409    }
410    int childCount = layer->countChildren();
411    stream->write32(childCount);
412    for (int i = 0; i < childCount; i++)
413        serializeLayer(layer->getChild(i), stream);
414}
415
416LayerAndroid* deserializeLayer(int version, SkStream* stream)
417{
418    int type = stream->readU8();
419    if (type == LTNone)
420        return 0;
421    // Cast is to disambiguate between ctors.
422    LayerAndroid *layer;
423    if (type == LTLayerAndroid)
424        layer = new LayerAndroid((RenderLayer*) 0);
425    else if (type == LTScrollableLayerAndroid)
426        layer = new ScrollableLayerAndroid((RenderLayer*) 0);
427    else {
428        ALOGV("Unexpected layer type: %d, aborting!", type);
429        return 0;
430    }
431
432    // Layer fields
433    layer->setShouldInheritFromRootTransform(stream->readBool());
434    layer->setOpacity(stream->readScalar());
435    layer->setSize(stream->readScalar(), stream->readScalar());
436    layer->setPosition(stream->readScalar(), stream->readScalar());
437    layer->setAnchorPoint(stream->readScalar(), stream->readScalar());
438    layer->setMatrix(readMatrix(stream));
439    layer->setChildrenMatrix(readMatrix(stream));
440
441    // LayerAndroid fields
442    layer->m_haveClip = stream->readBool();
443
444    // Keep the legacy serialization/deserialization format...
445    bool isFixed = stream->readBool();
446
447    layer->m_backgroundColorSet = stream->readBool();
448
449    bool isIframe = stream->readBool();
450    // If we are a scrollable layer android, we are an iframe content
451    if (isIframe && type == LTScrollableLayerAndroid) {
452         IFrameContentLayerAndroid* iframeContent = new IFrameContentLayerAndroid(*layer);
453         layer->unref();
454         layer = iframeContent;
455    } else if (isIframe) { // otherwise we are just the iframe (we use it to compute offset)
456         IFrameLayerAndroid* iframe = new IFrameLayerAndroid(*layer);
457         layer->unref();
458         layer = iframe;
459    }
460
461    if (isFixed) {
462        FixedPositioning* fixedPosition = new FixedPositioning(layer);
463
464        fixedPosition->m_fixedLeft = readSkLength(stream);
465        fixedPosition->m_fixedTop = readSkLength(stream);
466        fixedPosition->m_fixedRight = readSkLength(stream);
467        fixedPosition->m_fixedBottom = readSkLength(stream);
468        fixedPosition->m_fixedMarginLeft = readSkLength(stream);
469        fixedPosition->m_fixedMarginTop = readSkLength(stream);
470        fixedPosition->m_fixedMarginRight = readSkLength(stream);
471        fixedPosition->m_fixedMarginBottom = readSkLength(stream);
472        fixedPosition->m_fixedRect = readSkRect(stream);
473        fixedPosition->m_renderLayerPos.setX(stream->readS32());
474        fixedPosition->m_renderLayerPos.setY(stream->readS32());
475
476        layer->setFixedPosition(fixedPosition);
477    } else {
478        // Not a fixed element, bypass the values in the stream
479        readSkLength(stream); // fixedLeft
480        readSkLength(stream); // fixedTop
481        readSkLength(stream); // fixedRight
482        readSkLength(stream); // fixedBottom
483        readSkLength(stream); // fixedMarginLeft
484        readSkLength(stream); // fixedMarginTop
485        readSkLength(stream); // fixedMarginRight
486        readSkLength(stream); // fixedMarginBottom
487        readSkRect(stream);   // fixedRect
488        stream->readS32();    // renderLayerPos.x()
489        stream->readS32();    // renderLayerPos.y()
490    }
491
492    layer->m_backfaceVisibility = stream->readBool();
493    layer->m_visible = stream->readBool();
494    layer->m_backgroundColor = stream->readU32();
495    layer->m_preserves3D = stream->readBool();
496    layer->m_anchorPointZ = stream->readScalar();
497    layer->m_drawOpacity = stream->readScalar();
498    bool hasContentsImage = stream->readBool();
499    if (hasContentsImage) {
500        int size = stream->readU32();
501        SkAutoMalloc storage(size);
502        stream->read(storage.get(), size);
503        SkFlattenableReadBuffer buffer(storage.get(), size);
504        SkBitmap contentsImage;
505        contentsImage.unflatten(buffer);
506        SkBitmapRef* imageRef = new SkBitmapRef(contentsImage);
507        layer->setContentsImage(imageRef);
508        delete imageRef;
509    }
510    bool hasRecordingPicture = stream->readBool();
511    if (hasRecordingPicture) {
512        SkPicture* picture = new SkPicture(stream);
513        PictureLayerContent* content = new PictureLayerContent(picture);
514        layer->setContent(content);
515        SkSafeUnref(content);
516        SkSafeUnref(picture);
517    }
518    int animationCount = stream->readU32(); // TODO: Support (maybe?)
519    readTransformationMatrix(stream, layer->m_transform);
520    readTransformationMatrix(stream, layer->m_childrenTransform);
521    if (type == LTScrollableLayerAndroid) {
522        ScrollableLayerAndroid* scrollableLayer =
523                static_cast<ScrollableLayerAndroid*>(layer);
524        scrollableLayer->m_scrollLimits.set(
525                stream->readScalar(),
526                stream->readScalar(),
527                stream->readScalar(),
528                stream->readScalar());
529    }
530    int childCount = stream->readU32();
531    for (int i = 0; i < childCount; i++) {
532        LayerAndroid *childLayer = deserializeLayer(version, stream);
533        if (childLayer)
534            layer->addChild(childLayer);
535    }
536    ALOGV("Created layer with id %d", layer->uniqueId());
537    return layer;
538}
539
540/*
541 * JNI registration
542 */
543static JNINativeMethod gSerializerMethods[] = {
544    { "nativeDumpLayerHierarchy", "(IILjava/io/OutputStream;[B)V",
545        (void*) nativeDumpLayerHierarchy },
546    { "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z",
547        (void*) nativeSerializeViewState },
548    { "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I",
549        (void*) nativeDeserializeViewState },
550};
551
552int registerViewStateSerializer(JNIEnv* env)
553{
554    return jniRegisterNativeMethods(env, "android/webkit/ViewStateSerializer",
555                                    gSerializerMethods, NELEM(gSerializerMethods));
556}
557
558}
559