Merge "Rename and simplify DisplayList Canvas classes"

This commit is contained in:
Chris Craik
2015-03-10 16:29:00 +00:00
committed by Android (Google) Code Review
10 changed files with 103 additions and 136 deletions

View File

@@ -16,6 +16,7 @@
package android.view;
import android.annotation.NonNull;
import android.graphics.Bitmap;
import android.graphics.CanvasProperty;
import android.graphics.NinePatch;
@@ -24,19 +25,50 @@ import android.graphics.Path;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Pools.SynchronizedPool;
/**
* An implementation of Canvas on top of OpenGL ES 2.0.
* An implementation of a GL canvas that records drawing operations.
* This is intended for use with a DisplayList. This class keeps a list of all the Paint and
* Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
* the DisplayList is still holding a native reference to the memory.
*/
class GLES20Canvas extends HardwareCanvas {
class DisplayListCanvas extends HardwareCanvas {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;
private static final SynchronizedPool<DisplayListCanvas> sPool =
new SynchronizedPool<DisplayListCanvas>(POOL_LIMIT);
RenderNode mNode;
private int mWidth;
private int mHeight;
private float[] mPoint;
private float[] mLine;
private Rect mClipBounds;
private RectF mPathBounds;
static DisplayListCanvas obtain(@NonNull RenderNode node) {
if (node == null) throw new IllegalArgumentException("node cannot be null");
DisplayListCanvas canvas = sPool.acquire();
if (canvas == null) {
canvas = new DisplayListCanvas();
}
canvas.mNode = node;
return canvas;
}
void recycle() {
mNode = null;
sPool.release(this);
}
long finishRecording() {
return nFinishRecording(mNativeCanvasWrapper);
}
@Override
public boolean isRecordingFor(Object o) {
return o == mNode;
}
///////////////////////////////////////////////////////////////////////////
// JNI
@@ -53,8 +85,8 @@ class GLES20Canvas extends HardwareCanvas {
// Constructors
///////////////////////////////////////////////////////////////////////////
// TODO: Merge with GLES20RecordingCanvas
protected GLES20Canvas() {
private DisplayListCanvas() {
super(nCreateDisplayListRenderer());
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import android.annotation.NonNull;
import android.util.Pools.SynchronizedPool;
/**
* An implementation of a GL canvas that records drawing operations.
* This is intended for use with a DisplayList. This class keeps a list of all the Paint and
* Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
* the DisplayList is still holding a native reference to the memory.
*/
class GLES20RecordingCanvas extends GLES20Canvas {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;
private static final SynchronizedPool<GLES20RecordingCanvas> sPool =
new SynchronizedPool<GLES20RecordingCanvas>(POOL_LIMIT);
RenderNode mNode;
private GLES20RecordingCanvas() {
super();
}
static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
if (node == null) throw new IllegalArgumentException("node cannot be null");
GLES20RecordingCanvas canvas = sPool.acquire();
if (canvas == null) {
canvas = new GLES20RecordingCanvas();
}
canvas.mNode = node;
return canvas;
}
void recycle() {
mNode = null;
sPool.release(this);
}
long finishRecording() {
return nFinishRecording(mNativeCanvasWrapper);
}
@Override
public boolean isRecordingFor(Object o) {
return o == mNode;
}
}

View File

@@ -119,6 +119,6 @@ public abstract class HardwareCanvas extends Canvas {
CanvasProperty<Paint> paint);
public static void setProperty(String name, String value) {
GLES20Canvas.setProperty(name, value);
DisplayListCanvas.setProperty(name, value);
}
}

View File

@@ -205,7 +205,7 @@ public abstract class HardwareRenderer {
* false otherwise
*/
public static boolean isAvailable() {
return GLES20Canvas.isAvailable();
return DisplayListCanvas.isAvailable();
}
/**
@@ -423,7 +423,7 @@ public abstract class HardwareRenderer {
*/
static HardwareRenderer create(Context context, boolean translucent) {
HardwareRenderer renderer = null;
if (GLES20Canvas.isAvailable()) {
if (DisplayListCanvas.isAvailable()) {
renderer = new ThreadedRenderer(context, translucent);
}
return renderer;

View File

@@ -225,7 +225,7 @@ public class RenderNode {
* @see #isValid()
*/
public HardwareCanvas start(int width, int height) {
HardwareCanvas canvas = GLES20RecordingCanvas.obtain(this);
HardwareCanvas canvas = DisplayListCanvas.obtain(this);
canvas.setViewport(width, height);
// The dirty rect should always be null for a display list
canvas.onPreDraw(null);
@@ -241,11 +241,11 @@ public class RenderNode {
* @see #isValid()
*/
public void end(HardwareCanvas endCanvas) {
if (!(endCanvas instanceof GLES20RecordingCanvas)) {
if (!(endCanvas instanceof DisplayListCanvas)) {
throw new IllegalArgumentException("Passed an invalid canvas to end!");
}
GLES20RecordingCanvas canvas = (GLES20RecordingCanvas) endCanvas;
DisplayListCanvas canvas = (DisplayListCanvas) endCanvas;
canvas.onPostDraw();
long renderNodeData = canvas.finishRecording();
nSetDisplayListData(mNativeRenderNode, renderNodeData);

View File

@@ -283,10 +283,10 @@ public class RenderNodeAnimator extends Animator {
}
public void setTarget(Canvas canvas) {
if (!(canvas instanceof GLES20RecordingCanvas)) {
if (!(canvas instanceof DisplayListCanvas)) {
throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
}
final GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
final DisplayListCanvas recordingCanvas = (DisplayListCanvas) canvas;
setTarget(recordingCanvas.mNode);
}

View File

@@ -41,25 +41,25 @@ LOCAL_SRC_FILES:= \
android_database_SQLiteDebug.cpp \
android_emoji_EmojiFactory.cpp \
android_view_DisplayEventReceiver.cpp \
android_view_Surface.cpp \
android_view_SurfaceControl.cpp \
android_view_SurfaceSession.cpp \
android_view_TextureView.cpp \
android_view_DisplayListCanvas.cpp \
android_view_GraphicBuffer.cpp \
android_view_HardwareLayer.cpp \
android_view_InputChannel.cpp \
android_view_InputDevice.cpp \
android_view_InputEventReceiver.cpp \
android_view_InputEventSender.cpp \
android_view_InputQueue.cpp \
android_view_KeyEvent.cpp \
android_view_KeyCharacterMap.cpp \
android_view_GraphicBuffer.cpp \
android_view_GLES20Canvas.cpp \
android_view_HardwareLayer.cpp \
android_view_ThreadedRenderer.cpp \
android_view_KeyEvent.cpp \
android_view_MotionEvent.cpp \
android_view_PointerIcon.cpp \
android_view_RenderNode.cpp \
android_view_RenderNodeAnimator.cpp \
android_view_Surface.cpp \
android_view_SurfaceControl.cpp \
android_view_SurfaceSession.cpp \
android_view_TextureView.cpp \
android_view_ThreadedRenderer.cpp \
android_view_VelocityTracker.cpp \
android_text_AndroidCharacter.cpp \
android_text_AndroidBidi.cpp \

View File

@@ -127,16 +127,16 @@ extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
extern int register_android_view_DisplayListCanvas(JNIEnv* env);
extern int register_android_view_GraphicBuffer(JNIEnv* env);
extern int register_android_view_HardwareLayer(JNIEnv* env);
extern int register_android_view_RenderNode(JNIEnv* env);
extern int register_android_view_RenderNodeAnimator(JNIEnv* env);
extern int register_android_view_GraphicBuffer(JNIEnv* env);
extern int register_android_view_GLES20Canvas(JNIEnv* env);
extern int register_android_view_HardwareLayer(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
extern int register_android_view_SurfaceControl(JNIEnv* env);
extern int register_android_view_SurfaceSession(JNIEnv* env);
extern int register_android_view_TextureView(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env);
extern int register_android_database_CursorWindow(JNIEnv* env);
extern int register_android_database_SQLiteConnection(JNIEnv* env);
@@ -1179,7 +1179,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_view_RenderNode),
REG_JNI(register_android_view_RenderNodeAnimator),
REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_DisplayListCanvas),
REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_ThreadedRenderer),
REG_JNI(register_android_view_Surface),

View File

@@ -50,43 +50,43 @@ static struct {
// Setup
// ----------------------------------------------------------------------------
static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_setViewport(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint width, jint height) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->setViewport(width, height);
}
static void android_view_GLES20Canvas_setHighContrastText(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_setHighContrastText(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean highContrastText) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->setHighContrastText(highContrastText);
}
static void android_view_GLES20Canvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean reorderEnable) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->insertReorderBarrier(reorderEnable);
}
static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_prepare(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->prepare();
}
static void android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_prepareDirty(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint left, jint top, jint right, jint bottom) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->prepareDirty(left, top, right, bottom);
}
static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_finish(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
renderer->finish();
}
static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
static void android_view_DisplayListCanvas_setProperty(JNIEnv* env,
jobject clazz, jstring name, jstring value) {
if (!Caches::hasInstance()) {
ALOGW("can't set property, no Caches instance");
@@ -108,7 +108,7 @@ static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
// Functor
// ----------------------------------------------------------------------------
static void android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong functorPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
@@ -120,11 +120,11 @@ static void android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject cl
// Misc
// ----------------------------------------------------------------------------
static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
static jint android_view_DisplayListCanvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
return Caches::getInstance().maxTextureSize;
}
static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
static jint android_view_DisplayListCanvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
return Caches::getInstance().maxTextureSize;
}
@@ -132,7 +132,7 @@ static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject c
// Drawing
// ----------------------------------------------------------------------------
static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_drawPatch(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong bitmapPtr, jlong patchPtr,
float left, float top, float right, float bottom, jlong paintPtr) {
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
@@ -143,7 +143,7 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
}
static void android_view_GLES20Canvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -157,7 +157,7 @@ static void android_view_GLES20Canvas_drawRoundRectProps(JNIEnv* env, jobject cl
renderer->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
}
static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
@@ -167,7 +167,7 @@ static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz
renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
}
static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
@@ -201,17 +201,17 @@ static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject cla
// Display lists
// ----------------------------------------------------------------------------
static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
jobject clazz, jlong rendererPtr) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
return reinterpret_cast<jlong>(renderer->finishRecording());
}
static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
static jlong android_view_DisplayListCanvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
return reinterpret_cast<jlong>(new DisplayListRenderer);
}
static void android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
jobject clazz, jlong rendererPtr, jlong renderNodePtr,
jint flags) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -224,7 +224,7 @@ static void android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
// Layers
// ----------------------------------------------------------------------------
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
@@ -235,7 +235,7 @@ static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
// Common
// ----------------------------------------------------------------------------
static jboolean android_view_GLES20Canvas_isAvailable(JNIEnv* env, jobject clazz) {
static jboolean android_view_DisplayListCanvas_isAvailable(JNIEnv* env, jobject clazz) {
char prop[PROPERTY_VALUE_MAX];
if (property_get("ro.kernel.qemu", prop, NULL) == 0) {
// not in the emulator
@@ -261,36 +261,36 @@ android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject java
// JNI Glue
// ----------------------------------------------------------------------------
const char* const kClassPathName = "android/view/GLES20Canvas";
const char* const kClassPathName = "android/view/DisplayListCanvas";
static JNINativeMethod gMethods[] = {
{ "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
{ "nSetHighContrastText","(JZ)V", (void*) android_view_GLES20Canvas_setHighContrastText },
{ "nInsertReorderBarrier","(JZ)V", (void*) android_view_GLES20Canvas_insertReorderBarrier },
{ "nPrepare", "(J)V", (void*) android_view_GLES20Canvas_prepare },
{ "nPrepareDirty", "(JIIII)V", (void*) android_view_GLES20Canvas_prepareDirty },
{ "nFinish", "(J)V", (void*) android_view_GLES20Canvas_finish },
{ "nIsAvailable", "()Z", (void*) android_view_DisplayListCanvas_isAvailable },
{ "nSetViewport", "(JII)V", (void*) android_view_DisplayListCanvas_setViewport },
{ "nSetHighContrastText","(JZ)V", (void*) android_view_DisplayListCanvas_setHighContrastText },
{ "nInsertReorderBarrier","(JZ)V", (void*) android_view_DisplayListCanvas_insertReorderBarrier },
{ "nPrepare", "(J)V", (void*) android_view_DisplayListCanvas_prepare },
{ "nPrepareDirty", "(JIIII)V", (void*) android_view_DisplayListCanvas_prepareDirty },
{ "nFinish", "(J)V", (void*) android_view_DisplayListCanvas_finish },
{ "nSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
(void*) android_view_GLES20Canvas_setProperty },
(void*) android_view_DisplayListCanvas_setProperty },
{ "nCallDrawGLFunction", "(JJ)V", (void*) android_view_GLES20Canvas_callDrawGLFunction },
{ "nCallDrawGLFunction", "(JJ)V", (void*) android_view_DisplayListCanvas_callDrawGLFunction },
{ "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_GLES20Canvas_drawPatch },
{ "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_DisplayListCanvas_drawPatch },
{ "nDrawRects", "(JJJ)V", (void*) android_view_GLES20Canvas_drawRegionAsRects },
{ "nDrawRoundRect", "(JJJJJJJJ)V", (void*) android_view_GLES20Canvas_drawRoundRectProps },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_GLES20Canvas_drawCircleProps },
{ "nDrawRects", "(JJJ)V", (void*) android_view_DisplayListCanvas_drawRegionAsRects },
{ "nDrawRoundRect", "(JJJJJJJJ)V", (void*) android_view_DisplayListCanvas_drawRoundRectProps },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_DisplayListCanvas_drawCircleProps },
{ "nFinishRecording", "(J)J", (void*) android_view_GLES20Canvas_finishRecording },
{ "nDrawRenderNode", "(JJI)V", (void*) android_view_GLES20Canvas_drawRenderNode },
{ "nFinishRecording", "(J)J", (void*) android_view_DisplayListCanvas_finishRecording },
{ "nDrawRenderNode", "(JJI)V", (void*) android_view_DisplayListCanvas_drawRenderNode },
{ "nCreateDisplayListRenderer", "()J", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
{ "nCreateDisplayListRenderer", "()J", (void*) android_view_DisplayListCanvas_createDisplayListRenderer },
{ "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer },
{ "nDrawLayer", "(JJFF)V", (void*) android_view_DisplayListCanvas_drawLayer },
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureHeight },
};
static JNINativeMethod gActivityThreadMethods[] = {
@@ -298,7 +298,7 @@ static JNINativeMethod gActivityThreadMethods[] = {
(void*) android_app_ActivityThread_dumpGraphics }
};
int register_android_view_GLES20Canvas(JNIEnv* env) {
int register_android_view_DisplayListCanvas(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, "android/graphics/Rect");
gRectClassInfo.set = GetMethodIDOrDie(env, clazz, "set", "(IIII)V");

View File

@@ -33,7 +33,7 @@ public class Utilities {
private static Method sPropertyMethod;
static {
try {
Class<?> c = Class.forName("android.view.GLES20Canvas");
Class<?> c = Class.forName("android.view.DisplayListCanvas");
sPropertyMethod = c.getDeclaredMethod("setProperty", String.class, String.class);
if (!sPropertyMethod.isAccessible()) sPropertyMethod.setAccessible(true);
} catch (ClassNotFoundException e) {