OSDN Git Service

Determine whether to use OpenGL renderer at runtime
authorChih-Wei Huang <cwhuang@linux.org.tw>
Thu, 20 Aug 2015 12:27:41 +0000 (20:27 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Tue, 22 Dec 2015 04:13:53 +0000 (12:13 +0800)
Add sanity check to RenderNodeAnimator to avoid crashing Launcher3.

core/java/android/view/RenderNodeAnimator.java
core/jni/android/graphics/Bitmap.cpp
core/jni/android/graphics/Graphics.cpp
core/jni/android/graphics/GraphicsJNI.h
core/jni/android/graphics/NinePatch.cpp
core/jni/android/graphics/Path.cpp
core/jni/android_view_GLES20Canvas.cpp

index 7b35a3b..305f2dd 100644 (file)
@@ -144,14 +144,11 @@ public class RenderNodeAnimator extends Animator {
         mNativePtr = new VirtualRefBasePtr(ptr);
     }
 
-    private void checkMutable() {
+    private boolean checkMutable() {
         if (mState != STATE_PREPARE) {
             throw new IllegalStateException("Animator has already started, cannot change it now!");
         }
-        if (mNativePtr == null) {
-            throw new IllegalStateException("Animator's target has been destroyed "
-                    + "(trying to modify an animation after activity destroy?)");
-        }
+        return (mNativePtr != null);
     }
 
     static boolean isNativeInterpolator(TimeInterpolator interpolator) {
@@ -165,6 +162,7 @@ public class RenderNodeAnimator extends Animator {
         if (isNativeInterpolator(mInterpolator)) {
             ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
         } else {
+            if (mNativePtr == null) return;
             long duration = nGetDuration(mNativePtr.get());
             ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration);
         }
@@ -291,7 +289,7 @@ public class RenderNodeAnimator extends Animator {
     }
 
     private void setTarget(RenderNode node) {
-        checkMutable();
+        if (!checkMutable()) return;
         if (mTarget != null) {
             throw new IllegalStateException("Target already set!");
         }
@@ -301,13 +299,13 @@ public class RenderNodeAnimator extends Animator {
     }
 
     public void setStartValue(float startValue) {
-        checkMutable();
+        if (!checkMutable()) return;
         nSetStartValue(mNativePtr.get(), startValue);
     }
 
     @Override
     public void setStartDelay(long startDelay) {
-        checkMutable();
+        if (!checkMutable()) return;
         if (startDelay < 0) {
             throw new IllegalArgumentException("startDelay must be positive; " + startDelay);
         }
@@ -322,7 +320,7 @@ public class RenderNodeAnimator extends Animator {
 
     @Override
     public RenderNodeAnimator setDuration(long duration) {
-        checkMutable();
+        if (!checkMutable()) return this;
         if (duration < 0) {
             throw new IllegalArgumentException("duration must be positive; " + duration);
         }
@@ -348,7 +346,7 @@ public class RenderNodeAnimator extends Animator {
 
     @Override
     public void setInterpolator(TimeInterpolator interpolator) {
-        checkMutable();
+        if (!checkMutable()) return;
         mInterpolator = interpolator;
     }
 
@@ -490,7 +488,7 @@ public class RenderNodeAnimator extends Animator {
 
     @Override
     public void setAllowRunningAsynchronously(boolean mayRunAsync) {
-        checkMutable();
+        if (!checkMutable()) return;
         nSetAllowRunningAsync(mNativePtr.get(), mayRunAsync);
     }
 
index 3079218..67108d5 100755 (executable)
@@ -365,7 +365,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
 static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
 #ifdef USE_OPENGL_RENDERER
-    if (android::uirenderer::ResourceCache::hasInstance()) {
+    if (GraphicsJNI::useOpenglRenderer() && android::uirenderer::ResourceCache::hasInstance()) {
         android::uirenderer::ResourceCache::getInstance().destructor(bitmap);
         return;
     }
@@ -376,7 +376,7 @@ static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
 static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
 #ifdef USE_OPENGL_RENDERER
-    if (android::uirenderer::ResourceCache::hasInstance()) {
+    if (GraphicsJNI::useOpenglRenderer() && android::uirenderer::ResourceCache::hasInstance()) {
         bool result;
         result = android::uirenderer::ResourceCache::getInstance().recycle(bitmap);
         return result ? JNI_TRUE : JNI_FALSE;
index 3ea9b58..accc9dc 100644 (file)
@@ -10,6 +10,7 @@
 #include "SkMath.h"
 #include "SkPicture.h"
 #include "SkRegion.h"
+#include <cutils/properties.h>
 #include <android_runtime/AndroidRuntime.h>
 
 void doThrowNPE(JNIEnv* env) {
@@ -40,6 +41,17 @@ void doThrowIOE(JNIEnv* env, const char* msg) {
     jniThrowException(env, "java/io/IOException", msg);
 }
 
+static bool checkOpenglRenderer() {
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("debug.egl.hw", prop, "1");
+    return atoi(prop) == 1;
+}
+
+bool GraphicsJNI::useOpenglRenderer() {
+    static bool use_opengl_renderer = checkOpenglRenderer();
+    return use_opengl_renderer;
+}
+
 bool GraphicsJNI::hasException(JNIEnv *env) {
     if (env->ExceptionCheck() != 0) {
         ALOGE("*** Uncaught exception returned from Java call!\n");
index 42973ba..55f2987 100644 (file)
@@ -26,6 +26,8 @@ public:
         kBitmapCreateFlag_Premultiplied = 0x2,
     };
 
+    static bool useOpenglRenderer();
+
     // returns true if an exception is set (and dumps it out to the Log)
     static bool hasException(JNIEnv*);
 
index be62fdd..9ee9a58 100644 (file)
@@ -80,7 +80,7 @@ public:
     static void finalize(JNIEnv* env, jobject, jlong patchHandle) {
         int8_t* patch = reinterpret_cast<int8_t*>(patchHandle);
 #ifdef USE_OPENGL_RENDERER
-        if (android::uirenderer::ResourceCache::hasInstance()) {
+        if (GraphicsJNI::useOpenglRenderer() && android::uirenderer::ResourceCache::hasInstance()) {
             Res_png_9patch* p = (Res_png_9patch*) patch;
             android::uirenderer::ResourceCache::getInstance().destructor(p);
             return;
index 30ce58d..abf926a 100644 (file)
@@ -39,7 +39,7 @@ public:
     static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
 #ifdef USE_OPENGL_RENDERER
-        if (android::uirenderer::ResourceCache::hasInstance()) {
+        if (GraphicsJNI::useOpenglRenderer() && android::uirenderer::ResourceCache::hasInstance()) {
             android::uirenderer::ResourceCache::getInstance().destructor(obj);
             return;
         }
index 9bbd4fc..e201320 100644 (file)
@@ -830,7 +830,7 @@ static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz
     char prop[PROPERTY_VALUE_MAX];
     if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
         // not in the emulator
-        return JNI_TRUE;
+        return GraphicsJNI::useOpenglRenderer() ? JNI_TRUE : JNI_FALSE;
     }
     // In the emulator this property will be set to 1 when hardware GLES is
     // enabled, 0 otherwise. On old emulator versions it will be undefined.
@@ -848,6 +848,7 @@ static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz
 static void
 android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
 #ifdef USE_OPENGL_RENDERER
+    if (!GraphicsJNI::useOpenglRenderer()) return;
     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
     android::uirenderer::renderthread::RenderProxy::outputLogBuffer(fd);
 #endif // USE_OPENGL_RENDERER
@@ -975,8 +976,10 @@ static JNINativeMethod gActivityThreadMethods[] = {
 
 int register_android_view_GLES20Canvas(JNIEnv* env) {
     jclass clazz;
-    FIND_CLASS(clazz, "android/graphics/Rect");
-    GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
+    if (GraphicsJNI::useOpenglRenderer()) {
+        FIND_CLASS(clazz, "android/graphics/Rect");
+        GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V");
+    }
 
     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
 }