Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca481601 authored by John Reck's avatar John Reck Committed by Android (Google) Code Review
Browse files

Merge "Throw ISE on too-big-views-with-layers"

parents d1e01b76 c25e506f
Loading
Loading
Loading
Loading
+43 −13
Original line number Diff line number Diff line
@@ -49,6 +49,14 @@ using namespace android::uirenderer::renderthread;

static jmethodID gRunnableMethod;

static JNIEnv* getenv(JavaVM* vm) {
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
    }
    return env;
}

class JavaTask : public RenderTask {
public:
    JavaTask(JNIEnv* env, jobject jrunnable) {
@@ -57,20 +65,13 @@ public:
    }

    virtual void run() {
        env()->CallVoidMethod(mRunnable, gRunnableMethod);
        env()->DeleteGlobalRef(mRunnable);
        JNIEnv* env = getenv(mVm);
        env->CallVoidMethod(mRunnable, gRunnableMethod);
        env->DeleteGlobalRef(mRunnable);
        delete this;
    };

private:
    JNIEnv* env() {
        JNIEnv* env;
        if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
            return 0;
        }
        return env;
    }

    JavaVM* mVm;
    jobject mRunnable;
};
@@ -122,12 +123,34 @@ private:
    std::vector<OnFinishedEvent> mOnFinishedEvents;
};

class RootRenderNode : public RenderNode, public AnimationHook {
class RenderingException : public MessageHandler {
public:
    RootRenderNode() : RenderNode() {
    RenderingException(JavaVM* vm, const std::string& message)
            : mVm(vm)
            , mMessage(message) {
    }

    virtual void handleMessage(const Message&) {
        throwException(mVm, mMessage);
    }

    static void throwException(JavaVM* vm, const std::string& message) {
        JNIEnv* env = getenv(vm);
        jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
    }

private:
    JavaVM* mVm;
    std::string mMessage;
};

class RootRenderNode : public RenderNode, AnimationHook, ErrorHandler {
public:
    RootRenderNode(JNIEnv* env) : RenderNode() {
        mLooper = Looper::getForThread();
        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
                "Must create RootRenderNode on a thread with a looper!");
        env->GetJavaVM(&mVm);
    }

    virtual ~RootRenderNode() {}
@@ -137,10 +160,16 @@ public:
        mOnFinishedEvents.push_back(event);
    }

    virtual void onError(const std::string& message) {
        mLooper->sendMessage(new RenderingException(mVm, message), 0);
    }

    virtual void prepareTree(TreeInfo& info) {
        info.animationHook = this;
        info.errorHandler = this;
        RenderNode::prepareTree(info);
        info.animationHook = NULL;
        info.errorHandler = NULL;

        // post all the finished stuff
        if (mOnFinishedEvents.size()) {
@@ -160,6 +189,7 @@ protected:
private:
    sp<Looper> mLooper;
    std::vector<OnFinishedEvent> mOnFinishedEvents;
    JavaVM* mVm;
};

static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
@@ -178,7 +208,7 @@ static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
}

static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
    RootRenderNode* node = new RootRenderNode();
    RootRenderNode* node = new RootRenderNode(env);
    node->incStrong(0);
    node->setName("RootRenderNode");
    return reinterpret_cast<jlong>(node);
+14 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "RenderNode.h"

#include <algorithm>
#include <string>

#include <SkCanvas.h>
#include <algorithm>
@@ -158,7 +159,10 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
        applyLayerPropertiesToLayer(info);
        damageSelf(info);
    } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) {
        LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight());
        if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) {
            LayerRenderer::destroyLayer(mLayer);
            mLayer = 0;
        }
        damageSelf(info);
    }

@@ -166,6 +170,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
    info.damageAccumulator->peekAtDirty(&dirty);
    info.damageAccumulator->popTransform();

    if (!mLayer) {
        if (info.errorHandler) {
            std::string msg = "Unable to create layer for ";
            msg += getName();
            info.errorHandler->onError(msg);
        }
        return;
    }

    if (!dirty.isEmpty()) {
        mLayer->updateDeferred(this, dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom);
    }
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#ifndef TREEINFO_H
#define TREEINFO_H

#include <string>

#include <utils/Timers.h>

#include "DamageAccumulator.h"
@@ -35,6 +37,13 @@ protected:
    ~AnimationHook() {}
};

class ErrorHandler {
public:
    virtual void onError(const std::string& message) = 0;
protected:
    ~ErrorHandler() {}
};

// This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
class TreeInfo {
    PREVENT_COPY_AND_ASSIGN(TreeInfo);
@@ -65,6 +74,7 @@ public:
        , prepareTextures(mode == MODE_FULL)
        , damageAccumulator(NullDamageAccumulator::instance())
        , renderer(0)
        , errorHandler(0)
    {}

    const TraversalMode mode;
@@ -78,6 +88,7 @@ public:
    // The renderer that will be drawing the next frame. Use this to push any
    // layer updates or similar. May be NULL.
    OpenGLRenderer* renderer;
    ErrorHandler* errorHandler;

    struct Out {
        Out()