Throw ISE on too-big-views-with-layers
Bug: 12971954
Change-Id: I3ef995e91f236014b0a72a90846ef19ce6dc42b1
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 815c4a7..2b94b65 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -49,6 +49,14 @@
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 @@
}
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 @@
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 @@
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 @@
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 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);