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

This commit is contained in:
John Reck
2014-06-18 21:40:56 +00:00
committed by Android (Google) Code Review
3 changed files with 68 additions and 14 deletions

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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()